First commit

This commit is contained in:
2022-04-27 16:08:20 -04:00
commit 561a8479b7
270 changed files with 158521 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
*.o
*.d
+113
View File
@@ -0,0 +1,113 @@
#
# There exist several targets which are by default empty and which can be
# used for execution of your targets. These targets are usually executed
# before and after some main targets. They are:
#
# .build-pre: called before 'build' target
# .build-post: called after 'build' target
# .clean-pre: called before 'clean' target
# .clean-post: called after 'clean' target
# .clobber-pre: called before 'clobber' target
# .clobber-post: called after 'clobber' target
# .all-pre: called before 'all' target
# .all-post: called after 'all' target
# .help-pre: called before 'help' target
# .help-post: called after 'help' target
#
# Targets beginning with '.' are not intended to be called on their own.
#
# Main targets can be executed directly, and they are:
#
# build build a specific configuration
# clean remove built files from a configuration
# clobber remove all built files
# all build all configurations
# help print help mesage
#
# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
# .help-impl are implemented in nbproject/makefile-impl.mk.
#
# Available make variables:
#
# CND_BASEDIR base directory for relative paths
# CND_DISTDIR default top distribution directory (build artifacts)
# CND_BUILDDIR default top build directory (object files, ...)
# CONF name of current configuration
# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration)
# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration)
# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration)
# CND_PACKAGE_DIR_${CONF} directory of package (current configuration)
# CND_PACKAGE_NAME_${CONF} name of package (current configuration)
# CND_PACKAGE_PATH_${CONF} path to package (current configuration)
#
# NOCDDL
# Environment
MKDIR=mkdir
CP=cp
CCADMIN=CCadmin
RANLIB=ranlib
# build
build: .build-post
.build-pre:
# Add your pre 'build' code here...
.build-post: .build-impl
# Add your post 'build' code here...
# clean
clean: .clean-post
.clean-pre:
# Add your pre 'clean' code here...
# WARNING: the IDE does not call this target since it takes a long time to
# simply run make. Instead, the IDE removes the configuration directories
# under build and dist directly without calling make.
# This target is left here so people can do a clean when running a clean
# outside the IDE.
.clean-post: .clean-impl
# Add your post 'clean' code here...
# clobber
clobber: .clobber-post
.clobber-pre:
# Add your pre 'clobber' code here...
.clobber-post: .clobber-impl
# Add your post 'clobber' code here...
# all
all: .all-post
.all-pre:
# Add your pre 'all' code here...
.all-post: .all-impl
# Add your post 'all' code here...
# help
help: .help-post
.help-pre:
# Add your pre 'help' code here...
.help-post: .help-impl
# Add your post 'help' code here...
# include project implementation makefile
include nbproject/Makefile-impl.mk
# include project make variables
include nbproject/Makefile-variables.mk
+265
View File
@@ -0,0 +1,265 @@
/*******************************************************************************
* *
* Copyright 2012 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C header file.
*/
/* ************************************************************************** */
/* Revision:
### 20120521 JFM
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
/* ************************************************************************** */
/* Includes */
#include "define.h"
#include "ADC.h"
#include "HallAcquisition.h"
#include "digitalio.h"
#include "PAStatus.h"
/* Globals */
unsigned int guiADCMode;
unsigned short egADCMotPhaseA;
unsigned short egADCMotPhaseB;
unsigned short egADCMotPhaseC;
/* Implementation */
//----------------------------------------------------------------------------
void InitADC(void)
{
//At boot, init ADC in normal mode...
guiADCMode = ADC_NORMAL_MODE;
//configure input pins as analog inputs.
TRISBbits.TRISB3 = 1;
AD1PCFGbits.PCFG3 = 0;
TRISBbits.TRISB4 = 1;
AD1PCFGbits.PCFG4 = 0;
TRISBbits.TRISB5 = 1;
AD1PCFGbits.PCFG5 = 0;
TRISBbits.TRISB8 = 1;
AD1PCFGbits.PCFG8 = 0;
TRISBbits.TRISB9 = 1;
AD1PCFGbits.PCFG9 = 0;
TRISBbits.TRISB11 = 1;
AD1PCFGbits.PCFG11 = 0;
TRISBbits.TRISB12 = 1;
AD1PCFGbits.PCFG12 = 0;
TRISBbits.TRISB13 = 1;
AD1PCFGbits.PCFG13 = 0;
AD1CON1 = 0;
AD1CON2 = 0;
AD1CON3 = 0;
//configure output format (unsigned int 16 bits)
AD1CON1bits.FORM = 0b000;
//configure clock source and prescaling
AD1CON3bits.ADRC = 0; //Use Peripheral clock
AD1CON3bits.ADCS = 4; //Acording to datasheet TAD must be min 83.33ns --> minimal prescaler applied to TPBclk = 8 --> Conversion time ~= 100ns
//AD1CON3bits.SAMC = 1; //Used in automatic sampling mode (scan mode). Shall be augmented if results are not accurate. See datasheet.
AD1CON3bits.SAMC = 30; //Used in automatic sampling mode (scan mode). Shall be augmented if results are not accurate. See datasheet.
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int ADCEnterHallACQMode(void)
{
//configure ADC module
AD1CON1bits.ON = 0; //stop ADC to reconfigure.
IEC1bits.AD1IE = 0; //disable ADC interrupt for now
AD1CHS = 0; //Reset channel source since input source is controlled by hardware in scan mode.
AD1CON2 = 0;
AD1CSSL = 0;
AD1CON1bits.SSRC = 0b111; //manual conversion start. Clearing SAMP starts conversion. See AD1CON3bits.SAMC for sampling time.
// AD1CON1bits.SSRC = 0b000; //manual conversion start. Clearing SAMP starts conversion. See AD1CON3bits.SAMC for sampling time.
AD1CON1bits.CLRASAM = 1;
AD1CON1bits.ASAM = 1;
//configure scan mode
AD1CON2bits.CSCNA = 1; //enable scan mode
AD1CON2bits.SMPI = 2; //Generate interrupt after the 3rd conversion.
AD1CSSLbits.CSSL11= 1; //select Phase A input in scan sequence
AD1CSSLbits.CSSL12= 1; //select Phase B input in scan sequence
AD1CSSLbits.CSSL13= 1; //select Phase C input in scan sequence
AD1CON1bits.SAMP = 1 ;
IPC6bits.AD1IP = 5;
IPC6bits.AD1IS = 3;
IFS1bits.AD1IF = 0;
IEC1bits.AD1IE = 1; //enable ADC interrupt
AD1CON1bits.ON = 1; //enable ADC.
guiADCMode = ADC_HALL_ACQ_MODE;
return 1;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int ADCEnterTracesMode(void)
{
//trick to reuse code but force the good mode :)
ADCEnterHallACQMode();
guiADCMode = ADC_TRACE_MODE;
return 1;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int ADCEnterCBITMode(void)
{
//configure ADC module
AD1CON1bits.ON = 0; //stop ADC to reconfigure.
IEC1bits.AD1IE = 0; //disable ADC interrupt for now
AD1CHS = 0; //Reset channel source since input source is controlled by hardware in scan mode.
AD1CON2 = 0;
AD1CSSL = 0;
AD1CON1bits.SSRC = 0b111; //manual conversion start. Clearing SAMP starts conversion. See AD1CON3bits.SAMC for sampling time.
// AD1CON1bits.SSRC = 0b000; //manual conversion start. Clearing SAMP starts conversion. See AD1CON3bits.SAMC for sampling time.
AD1CON1bits.CLRASAM = 1;
AD1CON1bits.ASAM = 1;
//configure scan mode
AD1CON2bits.CSCNA = 1; //enable scan mode
AD1CON2bits.SMPI = 4; //Generate interrupt after the 5th conversion.
AD1CSSLbits.CSSL3= 1; //select Vref input in scan sequence
AD1CSSLbits.CSSL4= 1; //select 5V input in scan sequence
AD1CSSLbits.CSSL5= 1; //select 3.3V input in scan sequence
AD1CSSLbits.CSSL8= 1; //select Motor Thermistor input in scan sequence
AD1CSSLbits.CSSL9= 1; //select Drive Thermistor input in scan sequence
AD1CON1bits.SAMP = 1;
IPC6bits.AD1IP = 5;
IPC6bits.AD1IS = 3;
IFS1bits.AD1IF = 0;
IEC1bits.AD1IE = 1; //enable ADC interrupt
AD1CON1bits.ON = 1; //enable ADC.
guiADCMode = ADC_CBIT_MODE;
return 1;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// Starts acquistion and conversion of the 3 phases. The 3 inputs are scanned
// automatically by hardware and an interrupt is triggered when finished.
//
int ADCStartHallACQConversion(void)
{
AD1CON1bits.ASAM = 1;
AD1CON1bits.SAMP = 1; //start sampling and start conversion. Interrupt will be generated when data is ready
return 1;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int ADCStartTracesConversion(void)
{
AD1CON1bits.ASAM = 1;
AD1CON1bits.SAMP = 1; //start sampling and start conversion. Interrupt will be generated when data is ready
return 1;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int ADCStartCBITConversion(void)
{
if(guiADCMode == ADC_CBIT_MODE)
{
AD1CON1bits.ASAM = 1;
AD1CON1bits.SAMP = 1; //start sampling and start conversion. Interrupt will be generated when data is ready
return 1;
}
return 0;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int ADCStopConversion(void)
{
return 1;
}
//----------------------------------------------------------------------------
int ADCGetMode(void)
{
return guiADCMode;
}
//----------------------------------------------------------------------------
void __ISR(_ADC_VECTOR, ipl5) ADCInterrupt(void)
{
switch(guiADCMode)
{
case ADC_NORMAL_MODE:
{
break;
}
case ADC_CBIT_MODE:
{
estPAStatus.gusVoltageVref = ADC1BUF0;
estPAStatus.gusVoltage5V = ADC1BUF1;
estPAStatus.gusVoltage33V = ADC1BUF2;
estPAStatus.gusVoltageThermMot = ADC1BUF3;
estPAStatus.gusVoltageThermDrv = ADC1BUF4;
estPAStatus.IsDataReady = 1;
break;
}
case ADC_TRACE_MODE:
{
egADCMotPhaseA = ADC1BUF0;
egADCMotPhaseB = ADC1BUF1;
egADCMotPhaseC = ADC1BUF2;
break;
}
case ADC_HALL_ACQ_MODE:
{
//Update data structure.
if(gpstHallAcqDataPtr != 0 && gpstHallAcqDataPtr <= gpstHallAcqDataPtrEND)
{
gpstHallAcqDataPtr->MotPhaseA = ADC1BUF0;
gpstHallAcqDataPtr->MotPhaseB = ADC1BUF1;
gpstHallAcqDataPtr->MotPhaseC = ADC1BUF2;
gpstHallAcqDataPtr->AnalogDataUpToDate = 1;
}
break;
}
}
IFS1bits.AD1IF = 0;
}
//----------------------------------------------------------------------------
//EOF
+73
View File
@@ -0,0 +1,73 @@
/*******************************************************************************
* *
* Copyright 2012 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C header file.
*/
/* ************************************************************************** */
/* ¤Revision:
000 20120516 JFM,
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
#ifndef ADC_H
#define ADC_H
/* ************************************************************************** */
/* Externs */
extern unsigned short egADCMotPhaseA;
extern unsigned short egADCMotPhaseB;
extern unsigned short egADCMotPhaseC;
/* ************************************************************************** */
/* Defines */
#define ADC_VOLT_PER_BIT (float)0.003222656
/* ************************************************************************** */
/* Type definitions */
enum eADCModes
{
ADC_NORMAL_MODE,
ADC_CBIT_MODE,
ADC_TRACE_MODE,
ADC_HALL_ACQ_MODE,
ADC_MAX_MODE
};
/* ************************************************************************** */
/* Prototypes */
void InitADC(void);
int ADCStopConversion(void);
//Hall Acquisition Mode
int ADCEnterHallACQMode(void);
int ADCStartHallACQConversion(void);
//Traces Mode
int ADCEnterTracesMode(void);
int ADCStartTracesConversion(void);
//CBIT Mode
int ADCEnterCBITMode(void);
int ADCStartCBITConversion(void);
int ADCGetMode(void);
#endif //#define ADC_H
//EOF
+188
View File
@@ -0,0 +1,188 @@
//#include <proc/p32mx440f256h.h>
#include "BatteryMonitor.h"
#include "BoardCfg.h"
#include "timer.h"
#include "ina219.h"
#include "WiFiCtrl.h"
#include "I2C.h"
float mBatteryVoltage;
int mBatteryCurrent;
int mBatterySOC;
float mVoltageMeanSum;
int mVoltageMeanCount;
unsigned int mCurrentMeanSum;
int mCurrentMeanCount;
bool mCurrentModuleOK;
void InitBatteryMonitor()
{
mBatteryVoltage = 0;
mBatteryCurrent = 0;
mBatterySOC = 0;
mVoltageMeanCount = 0;
mCurrentMeanCount = 0;
mCurrentModuleOK = true;
TimerStart(BATTERY_MONITOR_TIMER,100);
//experimental stuff!
mVoltageMeanSum = 0.0;
mVoltageMeanCount = 0;
if(ina219Init() == RET_ERROR)
{
mCurrentModuleOK = false;
}
//ina219SetCalibration_16V_500mA();
// ina219SetCalibration_16V_200mA();
}
void BatteryMonitorTick()
{
static int NetworkSendCounter; //Every second (10 counts) we want to send the battery data.
if(IsTimerExpired(BATTERY_MONITOR_TIMER))
{
unsigned int adc;
double conv, raw;
AD1CHSbits.CH0SA = 1; //AN1
AD1CON1bits.SAMP = 0;
while(AD1CON1bits.DONE == 0);
adc = ADC1BUF0;
AD1CON1bits.SAMP = 1;
// adc &= 0xFFFE;
conv = (float)adc / 1023;
conv *= 3.36;
raw = conv;
conv *= 11;
//avoid rollovers in case the LORA network gets disconnected.
//This could go for a long time but 5000 samples is too much anyways.
if(mVoltageMeanCount >= 5000)
{
mVoltageMeanCount = 0;
mVoltageMeanSum = conv;
}
else
{
mVoltageMeanCount++;
mVoltageMeanSum += conv;
}
mBatteryVoltage = conv;
TimerStart(BATTERY_MONITOR_TIMER,100);
if(mCurrentModuleOK == true)
{
mBatteryCurrent = ina219GetCurrent_mA();
if(I2CWasLastTransactionOK() == 0 )
{
mCurrentModuleOK = false;
}
}
else
{
unsigned int Ref = 0;
AD1CHSbits.CH0SA = 0; //AN0
AD1CON1bits.SAMP = 0;
while(AD1CON1bits.DONE == 0);
Ref = ADC1BUF0;
AD1CON1bits.SAMP = 1;
AD1CHSbits.CH0SA = 2; //AN2
AD1CON1bits.SAMP = 0;
while(AD1CON1bits.DONE == 0);
adc = ADC1BUF0;
AD1CON1bits.SAMP = 1;
// adc &= 0xFFFE;
adc -= Ref;
conv = (double)adc * 1.0;
conv /= 1023;
conv *= 3.3; //Volts
conv /= 0.05; //Amps (50mV/A)
raw = conv;
//avoid rollovers in case the LORA network gets disconnected.
//This could go for a long time but 5000 samples is too much anyways.
if(mCurrentMeanCount >= 500)
{
mCurrentMeanCount = 1;
mCurrentMeanSum = adc;
}
else
{
mCurrentMeanCount++;
mCurrentMeanSum += adc;
}
mBatteryCurrent = adc;
//mBatteryCurrent = mCurrentMeanSum / mCurrentMeanCount;
}
}
}
float GetBatteryVoltage()
{
mBatteryVoltage = (mVoltageMeanSum/mVoltageMeanCount);
mVoltageMeanSum = 0.0;
mVoltageMeanCount = 0;
return mBatteryVoltage;
}
int GetSolarPanelCurrent()
{
//mBatteryCurrent = (mCurrentMeanSum/mCurrentMeanCount);
mVoltageMeanCount = 0;
mCurrentMeanSum = 0.0;
return mBatteryCurrent;
}
int GetBatterySOC()
{
return mBatterySOC;
}
int SendNetworkBatteryData()
{
// int VoltageMilliVolts = (int)(mBatteryVoltage * 1000);
// int BattCurrent = mBatteryCurrent;
//
// char BatData[10];
// BatData[0] = (char)(VoltageMilliVolts & 0x000000FF); //Battery Voltage 1
// VoltageMilliVolts >>= 8;
// BatData[1] = (char)(VoltageMilliVolts & 0x000000FF); //Battery Voltage 2
// BatData[2] = (char)(BattCurrent & 0x000000FF); //Solar panel Current 1
// BattCurrent >>= 8;
// BatData[3] = (char)(BattCurrent & 0x000000FF); //Solar panel Current 2
//
// SendNetworkData(BatData,4);
printf("Battery voltage: %f\n",mBatteryVoltage);
}
bool GetCurrentModuleOK()
{
return mCurrentModuleOK;
}
+26
View File
@@ -0,0 +1,26 @@
/*
* File: ChaletPowerRelay.h
* Author: JF
*
* Created on November 30, 2018, 7:33 PM
*/
#ifndef BATTERYMONITOR_H
#define BATTERYMONITOR_H
#include "define.h"
void InitBatteryMonitor();
void BatteryMonitorTick();
float GetBatteryVoltage();
int GetSolarPanelCurrent();
int GetBatterySOC();
int SendNetworkBatteryData();
bool GetCurrentModuleOK();
#endif /* BATTERYMONITOR_H */
+49
View File
@@ -0,0 +1,49 @@
/*
* File: BoardCfg.h
* Author: JF
*
* Created on November 26, 2018, 4:50 PM
*/
#ifndef BOARDCFG_H
#define BOARDCFG_H
#include "define.h"
static inline __attribute__((always_inline)) unsigned char SPICalculateBRG(unsigned int pb_clk, unsigned int spi_clk)
{
unsigned int brg;
brg = pb_clk / (2 * spi_clk);
if(pb_clk % (2 * spi_clk))
brg++;
if(brg > 0x100)
brg = 0x100;
if(brg)
brg--;
return (unsigned char) brg;
}
//
#ifdef FUBARINO_BRD
#include "BoardCfg_Fubarino.h"
#endif
//#ifdef PINGUINO_BRD
//#include "BoardCfg_Pinguino.h"
//#endif
#ifdef CHALETDUINO_BRD
#include "BoardCfg_Chaletduino.h"
#endif
#ifdef CHALETDUINO_V2_BRD
#include "BoardCfg_ChaletduinoV2.h"
#endif
int InitBoard();
#endif /* BOARDCFG_H */
@@ -0,0 +1,120 @@
/*
* File: DigitalIO_Chaletduino.h
* Author: JF
*
* Created on November 24, 2018, 3:20 PM
*/
#ifndef DIGITALIO_CHALETDUINO_H
#define DIGITALIO_CHALETDUINO_H
#ifdef __cplusplus
extern "C" {
#endif
/* ************************************************************************** */
/* Includes */
#include "define.h"
/* ************************************************************************** */
/* Defines */
//#include <plib.h>
#define SYS_FREQ (80000000L) //Clock period = 12.5 ns
#define PERIPHERAL_FREQ (80000000L)
//Output pins hardware definitions
//
#define HEARTBEAT_LED_2_PIN_DIR TRISEbits.TRISE6
#define HEARTBEAT_LED_2_PIN LATEbits.LATE6
#define HEARTBEAT_LED_2_TOGGLE_REG LATEINV
#define HEARTBEAT_LED_2_SET_REG LATESET
#define HEARTBEAT_LED_2_CLEAR_REG LATECLR
#define HEARTBEAT_LED_2_TOGGLE_MASK _LATG_LATE6_MASK
#define HEARTBEAT_LED_1_PIN_DIR TRISEbits.TRISE5
#define HEARTBEAT_LED_1_PIN LATEbits.LATE5
#define HEARTBEAT_LED_1_TOGGLE_REG LATEINV
#define HEARTBEAT_LED_1_SET_REG LATESET
#define HEARTBEAT_LED_1_CLEAR_REG LATECLR
#define HEARTBEAT_LED_1_TOGGLE_MASK _LATE_LATE5_MASK
#define LORA_ACTIVITY_LED_PIN_DIR TRISFbits.TRISF1
#define LORA_ACTIVITY_LED_PIN LATFbits.LATF1
#define LORA_ACTIVITY_LED_TOGGLE_REG LATFINV
#define LORA_ACTIVITY_LED_SET_REG LATFSET
#define LORA_ACTIVITY_LED_CLEAR_REG LATFCLR
#define LORA_ACTIVITY_LED_TOGGLE_MASK _LATE_LATF1_MASK
// #define GP_DEBUG_1_PIN_DIR TRISEbits.TRISE5
// #define GP_DEBUG_1_PIN LATEbits.LATE5
// #define GP_DEBUG_2_PIN_DIR TRISEbits.TRISE6
// #define GP_DEBUG_2_PIN LATEbits.LATE6
// #define SD_CARD_DETECT_PIN_DIR TRISDbits.TRISD8
// #define SD_CARD_DETECT_PIN LATDbits.LATD8
//SPI port defs
#define SPI_SDO_PIN_DIR TRISGbits.TRISG8
#define SPI_SDI_PIN_DIR TRISGbits.TRISG7
#define SPI_SCK_PIN_DIR TRISGbits.TRISG6
//SD Card
#define SD_SPI_SS_PIN_DIR TRISBbits.TRISB13
#define SD_SPI_SS_PIN LATBbits.LATB13
//SPI Flash
#define FLASH_SS_PIN_DIR TRISEbits.TRISE3
#define FLASH_SS_PIN LATEbits.LATE3
//Wifi (WINC3400 module)
#define WIFI_SPI_SS_PIN_DIR TRISEbits.TRISE0
#define WIFI_SPI_SS_PIN LATEbits.LATE0
#define WIFI_IRQ_PIN_DIR TRISDbits.TRISD0
#define WIFI_IRQ_PIN PORTDbits.RD0
// #define WIFI_SPI_CFG_PIN_DIR TRISEbits.TRISE1
// #define WIFI_SPI_CFG_PIN LATEbits.LATE1
#define WIFI_CHP_EN_PIN_DIR TRISEbits.TRISE2
#define WIFI_CHP_EN_PIN LATEbits.LATE2
#define WIFI_CHP_RST_PIN_DIR TRISEbits.TRISE4
#define WIFI_CHP_RST_PIN LATEbits.LATE4
//Chalet power relay
#define POWER_RELAY_ON_PIN_DIR TRISEbits.TRISE7
#define POWER_RELAY_ON_PIN LATEbits.LATE7 //X2-3
#define POWER_RELAY_OFF_PIN_DIR TRISGbits.TRISG9
#define POWER_RELAY_OFF_PIN LATGbits.LATG9 //X3-5
//Harakiri relay
#define HARAKIRI_RELAY_ON_PIN_DIR TRISBbits.TRISB0
#define HARAKIRI_RELAY_ON_PIN LATBbits.LATB0 //X2-3
//12V presence detection input
#define CHALET_12V_PRESENCE_PIN_DIR TRISBbits.TRISB15
#define CHALET_12V_PRESENCE_PIN PORTBbits.RB15 //X2-3
//Battery voltage measurement (analog input)
#define BATTERY_VOLTAGE_ANALOG_PIN_DIR TRISBbits.TRISB1
//Current sensor. Those pins tristate is controlled by the I2C module
#define CURRENT_MODULE_I2C_SCL_PIN_DIR TRISDbits.TRISD3
#define CURRENT_MODULE_I2C_SDA_PIN_DIR TRISDbits.TRISD2
/* ************************************************************************** */
/* Prototypes */
void InitDigitalIO(void);
#ifdef __cplusplus
}
#endif
#endif /* DIGITALIO_PINGUINO_H */
@@ -0,0 +1,170 @@
/*
* File: DigitalIO_Chaletduino.h
* Author: JF
*
* Created on November 24, 2018, 3:20 PM
*/
#ifndef DIGITALIO_CHALETDUINO_H
#define DIGITALIO_CHALETDUINO_H
#ifdef __cplusplus
extern "C" {
#endif
/* ************************************************************************** */
/* Includes */
#include "define.h"
/* ************************************************************************** */
/* Defines */
//#include <plib.h>
#define SYS_FREQ (80000000L) //Clock period = 12.5 ns
#define PERIPHERAL_FREQ (80000000L)
//Output pins hardware definitions
//
#define HEARTBEAT_LED_2_PIN_DIR TRISEbits.TRISE6
#define HEARTBEAT_LED_2_PIN LATEbits.LATE6
#define HEARTBEAT_LED_2_TOGGLE_REG LATEINV
#define HEARTBEAT_LED_2_SET_REG LATESET
#define HEARTBEAT_LED_2_CLEAR_REG LATECLR
#define HEARTBEAT_LED_2_TOGGLE_MASK _LATG_LATE6_MASK
#define HEARTBEAT_LED_1_PIN_DIR TRISEbits.TRISE5
#define HEARTBEAT_LED_1_PIN LATEbits.LATE5
#define HEARTBEAT_LED_1_TOGGLE_REG LATEINV
#define HEARTBEAT_LED_1_SET_REG LATESET
#define HEARTBEAT_LED_1_CLEAR_REG LATECLR
#define HEARTBEAT_LED_1_TOGGLE_MASK _LATE_LATE5_MASK
//#define LORA_ACTIVITY_LED_PIN_DIR TRISFbits.TRISF1
//#define LORA_ACTIVITY_LED_PIN LATFbits.LATF1
//#define LORA_ACTIVITY_LED_TOGGLE_REG LATFINV
//#define LORA_ACTIVITY_LED_SET_REG LATFSET
//#define LORA_ACTIVITY_LED_CLEAR_REG LATFCLR
//#define LORA_ACTIVITY_LED_TOGGLE_MASK _LATE_LATF1_MASK
// #define GP_DEBUG_1_PIN_DIR TRISEbits.TRISE5
// #define GP_DEBUG_1_PIN LATEbits.LATE5
// #define GP_DEBUG_2_PIN_DIR TRISEbits.TRISE6
// #define GP_DEBUG_2_PIN LATEbits.LATE6
// #define SD_CARD_DETECT_PIN_DIR TRISDbits.TRISD8
// #define SD_CARD_DETECT_PIN LATDbits.LATD8
//SPI port defs
#define SPI_SDO_PIN_DIR TRISGbits.TRISG8
#define SPI_SDI_PIN_DIR TRISGbits.TRISG7
#define SPI_SCK_PIN_DIR TRISGbits.TRISG6
//SD Card
#define SD_SPI_SS_PIN_DIR TRISBbits.TRISB13
#define SD_SPI_SS_PIN LATBbits.LATB13
//SPI Flash
#define FLASH_SS_PIN_DIR TRISEbits.TRISE3
#define FLASH_SS_PIN LATEbits.LATE3
//Wifi (WINC3400 module)
#define WIFI_SPI_SS_PIN_DIR TRISEbits.TRISE0
#define WIFI_SPI_SS_PIN LATEbits.LATE0
#define WIFI_IRQ_PIN_DIR TRISDbits.TRISD0
#define WIFI_IRQ_PIN PORTDbits.RD0
// #define WIFI_SPI_CFG_PIN_DIR TRISEbits.TRISE1
// #define WIFI_SPI_CFG_PIN LATEbits.LATE1
#define WIFI_CHP_EN_PIN_DIR TRISEbits.TRISE2
#define WIFI_CHP_EN_PIN LATEbits.LATE2
#define WIFI_CHP_RST_PIN_DIR TRISEbits.TRISE4
#define WIFI_CHP_RST_PIN LATEbits.LATE4
//Chalet power relay
#define POWER_RELAY_ON_PIN_DIR TRISEbits.TRISE7
#define POWER_RELAY_ON_PIN LATEbits.LATE7 //X2-
#define POWER_RELAY_OFF_PIN_DIR TRISGbits.TRISG9
#define POWER_RELAY_OFF_PIN LATGbits.LATG9 //X3-
//Harakiri relay
#define HARAKIRI_RELAY_ON_PIN_DIR TRISDbits.TRISD6
#define HARAKIRI_RELAY_ON_PIN LATDbits.LATD6
//12V presence detection input
#define CHALET_12V_PRESENCE_PIN_DIR TRISBbits.TRISB15
#define CHALET_12V_PRESENCE_PIN PORTBbits.RB15 //X2-
//Battery voltage measurement (analog input)
#define BATTERY_VOLTAGE_ANALOG_PIN_DIR TRISBbits.TRISB1 //X2-7
// //Current sensor. Those pins tristate is controlled by the I2C module
//#define CURRENT_MODULE_I2C_SCL_PIN_DIR TRISDbits.TRISD3
//#define CURRENT_MODULE_I2C_SDA_PIN_DIR TRISDbits.TRISD2
//Onboard temperature sensor (SPI)
#define TEMP_SENSOR_CS_PIN_DIR TRISDbits.TRISD4
#define TEMP_SENSOR_CS_PIN LATDbits.LATD4
#define TEMP_SENSOR_SPI_SDO_PIN_DIR TRISDbits.TRISD3
#define TEMP_SENSOR_SPI_SDI_PIN_DIR TRISDbits.TRISD2
#define TEMP_SENSOR_SPI_SCK_PIN_DIR TRISDbits.TRISD1
//Analog (Hall effect) current sensor
#define CURRENT_SENSOR_IN1_PIN_DIR TRISBbits.TRISB2
#define CURRENT_SENSOR_IN2_PIN_DIR TRISBbits.TRISB0
//LoRa
#define LORA_MODULE_RELAY_PIN_DIR TRISDbits.TRISD11
#define LORA_MODULE_RELAY_PIN LATDbits.LATD11
#define LORA_MODULE_M0_PIN_DIR TRISDbits.TRISD3 //V2
#define LORA_MODULE_M0_PIN LATDbits.LATD3
#define LORA_MODULE_M1_PIN_DIR TRISDbits.TRISD9
#define LORA_MODULE_M1_PIN LATDbits.LATD9
#define LORA_MODULE_INT_PIN_DIR TRISDbits.TRISD8
#define LORA_MODULE_INT_PIN PORTDbits.RD8
//#define LORA_MODULE_RX_LED_PIN_DIR TRISCbits.TRISC14
//#define LORA_MODULE_RX_LED_PIN LATCbits.LATC14
//#define LORA_MODULE_TX_LED_PIN_DIR TRISCbits.TRISC13
//#define LORA_MODULE_TX_LED_PIN LATCbits.LATC13
#define LORA_MODULE_RX_LED_PIN_DIR TRISBbits.TRISB4
#define LORA_MODULE_RX_LED_PIN LATBbits.LATB4
#define LORA_MODULE_TX_LED_PIN_DIR TRISFbits.TRISF1
#define LORA_MODULE_TX_LED_PIN LATFbits.LATF1
//LCD Screen
#define LCD_RS_PIN_DIR TRISDbits.TRISD5
#define LCD_RS_PIN LATDbits.LATD5
#define LCD_RW_PIN_DIR TRISBbits.TRISB13
#define LCD_RW_PIN LATBbits.LATB13
#define LCD_E_PIN_DIR TRISBbits.TRISB12
#define LCD_E_PIN LATBbits.LATB12
#define LCD_DB4_PIN_DIR TRISBbits.TRISB3
#define LCD_DB4_PIN LATBbits.LATB3
#define LCD_DB5_PIN_DIR TRISBbits.TRISB9
#define LCD_DB5_PIN LATBbits.LATB9
#define LCD_DB6_PIN_DIR TRISBbits.TRISB10
#define LCD_DB6_PIN LATBbits.LATB10
#define LCD_DB7_PIN_DIR TRISBbits.TRISB11
#define LCD_DB7_PIN LATBbits.LATB11
#define LCD_SCROLL_BTN_PIN_DIR TRISBbits.TRISB5
#define LCD_SCROLL_BTN_PIN PORTBbits.RB5
/* ************************************************************************** */
/* Prototypes */
void InitDigitalIO(void);
#ifdef __cplusplus
}
#endif
#endif /* DIGITALIO_PINGUINO_H */
+58
View File
@@ -0,0 +1,58 @@
/*
* File: DigitalIO_Fubarino.h
* Author: JF
*
* Created on November 24, 2018, 3:20 PM
*/
#ifndef DIGITALIO_FUBARINO_H
#define DIGITALIO_FUBARINO_H
#ifdef __cplusplus
extern "C" {
#endif
/* ************************************************************************** */
/* Includes */
#include "define.h"
/* ************************************************************************** */
/* Defines */
#define SYS_FREQ (80000000L) //Clock period = 12.5 ns
#define PERIPHERAL_FREQ (80000000L)
//Output pins hardware definitions
//
#define HEARTBEAT_LED_1_PIN_DIR TRISEbits.TRISE5
#define HEARTBEAT_LED_1_PIN LATEbits.LATE5
#define HEARTBEAT_LED_1_TOGGLE_REG LATEINV
#define HEARTBEAT_LED_1_SET_REG LATESET
#define HEARTBEAT_LED_1_CLEAR_REG LATECLR
#define HEARTBEAT_LED_1_TOGGLE_MASK _LATE_LATE5_MASK
#define HEARTBEAT_LED_2_PIN_DIR TRISEbits.TRISE2
#define HEARTBEAT_LED_2_PIN LATEbits.LATE2
#define HEARTBEAT_LED_2_TOGGLE_REG LATEINV
#define HEARTBEAT_LED_2_SET_REG LATESET
#define HEARTBEAT_LED_2_CLEAR_REG LATECLR
#define HEARTBEAT_LED_2_TOGGLE_MASK _LATE_LATE2_MASK
#define SD_SPI_SDO_PIN_DIR TRISGbits.TRISG8
#define SD_SPI_CS_PIN_DIR TRISGbits.TRISG9
#define SD_SPI_CS_PIN LATGbits.LATG9
#define SD_SPI_SDI_PIN_DIR TRISGbits.TRISG7
#define SD_SPI_SCK_PIN_DIR TRISGbits.TRISG6
/* ************************************************************************** */
/* Prototypes */
void InitDigitalIO(void);
#ifdef __cplusplus
}
#endif
#endif /* DIGITALIO_FUBARINO_H */
+104
View File
@@ -0,0 +1,104 @@
/*
* File: DigitalIO_Pinguino.h
* Author: JF
*
* Created on November 24, 2018, 3:20 PM
*/
#ifndef DIGITALIO_PINGUINO_H
#define DIGITALIO_PINGUINO_H
#ifdef __cplusplus
extern "C" {
#endif
/* ************************************************************************** */
/* Includes */
#include "define.h"
/* ************************************************************************** */
/* Defines */
#define SYS_FREQ (80000000L) //Clock period = 12.5 ns
#define PERIPHERAL_FREQ (80000000L)
//Output pins hardware definitions
//
// #define HEARTBEAT_LED_2_PIN_DIR TRISGbits.TRISG6
// #define HEARTBEAT_LED_2_PIN LATGbits.LATG6
// #define HEARTBEAT_LED_2_TOGGLE_REG LATGINV
// #define HEARTBEAT_LED_2_SET_REG LATGSET
// #define HEARTBEAT_LED_2_CLEAR_REG LATGCLR
// #define HEARTBEAT_LED_2_TOGGLE_MASK _LATG_LATG6_MASK
#define HEARTBEAT_LED_1_PIN_DIR TRISDbits.TRISD1
#define HEARTBEAT_LED_1_PIN LATDbits.LATD1
#define HEARTBEAT_LED_1_TOGGLE_REG LATDINV
#define HEARTBEAT_LED_1_SET_REG LATDSET
#define HEARTBEAT_LED_1_CLEAR_REG LATDCLR
#define HEARTBEAT_LED_1_TOGGLE_MASK _LATD_LATD1_MASK
// #define SD_CARD_DETECT_PIN_DIR TRISDbits.TRISD8
// #define SD_CARD_DETECT_PIN LATDbits.LATD8
//SPI port defs
#define SPI_SDO_PIN_DIR TRISGbits.TRISG8
#define SPI_SDI_PIN_DIR TRISGbits.TRISG7
#define SPI_SCK_PIN_DIR TRISGbits.TRISG6
//SD Card
#define SD_SPI_SS_PIN_DIR TRISBbits.TRISB13
#define SD_SPI_SS_PIN LATBbits.LATB13
//Wifi (WINC3400 module)
#define WIFI_SPI_SS_PIN_DIR TRISFbits.TRISF1
#define WIFI_SPI_SS_PIN LATFbits.LATF1
#define WIFI_IRQ_PIN_DIR TRISDbits.TRISD0
#define WIFI_IRQ_PIN PORTDbits.RD0
#define WIFI_WAKE_PIN_DIR TRISEbits.TRISE0
#define WIFI_WAKE_PIN LATEbits.LATE0
#define WIFI_SPI_CFG_PIN_DIR TRISEbits.TRISE1
#define WIFI_SPI_CFG_PIN LATEbits.LATE1
#define WIFI_CHP_EN_PIN_DIR TRISEbits.TRISE2
#define WIFI_CHP_EN_PIN LATEbits.LATE2
#define WIFI_CHP_RST_PIN_DIR TRISEbits.TRISE3
#define WIFI_CHP_RST_PIN LATEbits.LATE3
//Control knob encoder
#define KNOB_PH_A_PIN_DIR TRISDbits.TRISD8
#define KNOB_PH_A_PIN PORTDbits.RD8
#define KNOB_PH_B_PIN_DIR TRISDbits.TRISD7
#define KNOB_PH_B_PIN PORTDbits.RD7
#define KNOB_TGLE_BTN_PIN_DIR TRISDbits.TRISD11
#define KNOB_TGLE_BTN_PIN PORTDbits.RD11
//Led controller PWM
#define LED_PWM_PIN_DIR TRISDbits.TRISD2
#define LED_PWM_PIN LATDbits.LATD2
#define LED_PWM_VAL_REG OC3RS
//Misc CPU or board related defines
#define PWM_RANGE_MAX 16000
#define GP_DEBUG_1_PIN_DIR TRISEbits.TRISE5
#define GP_DEBUG_1_PIN LATEbits.LATE5
#define GP_DEBUG_2_PIN_DIR TRISEbits.TRISE6
#define GP_DEBUG_2_PIN LATEbits.LATE6
/* ************************************************************************** */
/* Prototypes */
void InitDigitalIO(void);
#ifdef __cplusplus
}
#endif
#endif /* DIGITALIO_PINGUINO_H */
+985
View File
@@ -0,0 +1,985 @@
//#include <proc/p32mx440f256h.h>
#include "BootloaderInterface.h"
#include "BootloaderProtocol.h"
#include "ProtocolDefs.h"
#include "BoardCfg.h"
#include "timer.h"
#include "WiFiCtrl.h"
#include "SPI_Flash.h"
#include "FlashMapping.h"
#include "NetworkProtocol.h"
#include "Syslog.h"
#include "checksum.h"
#include "FlashMapping.h"
#define BOOTLOADER_FLASH_ERASE_POLL_TIMEOUT 25//100 //ms
#define BOOTLOADER_FLASH_ERASE_MAX_POLL_COUNT 40//10 //One sector should not take more than 1s to erase...
#define BOOTLOADER_FLASH_WRITE_POLL_TIMEOUT 25//100 //ms
#define BOOTLOADER_FLASH_WRITE_MAX_POLL_COUNT 40//10 //One sector should not take more than 1s to erase...
unsigned char BootloaderBuffer[300];
int BootloaderInterfaceState;
int DataChunkWritten;
int CurDataChunkIndex;
int FirmwareUploaded;
int CurDataChunkSize;
int BooloaderFlashEraseState;
int BootloaderFlashErased;
unsigned int BootloaderCurFlashEraseAddress;
int BooloaderFlashErasePollCount;
int BootloaderFlashWriteState;
unsigned int BootloaderCurFlashWriteAddress;
int BootloaderFlashWritePollCount;
int BootloaderFirmwareChunkWriteCount;
char* BootloaderFlashWriteDataPtr;
int BootloaderInterfaceInit()
{
BootloaderProtocolInit();
BootloaderResetStateMachine();
BootloaderCheckFlashBootloaderData();
update_crc_32(0,0); //Force to populate the CRC32 table...
return 1;
}
void BootloaderInterfaceTick()
{
BootloaderInterfaceStateMachine(BOOTLOADER_TICK_EVENT,0);
}
void BootloaderExecuteCmd(char Cmd,bool CRCValid)
{
unsigned char *DataBufPtr = BootloaderProtocolGetDataBufferPtr();
if(CRCValid == 0)
{
printf("Bootloader received a frame with invalid CRC\n");
BootloaderInterfaceStateMachine(BOOTLOADER_NEW_CMD_EVENT,BOOTLOADER_SM_INVALID_CRC_CMD);
return;
}
switch(Cmd)
{
case BOOTLOADER_HEARTBEAT_REQUEST:
{
printf("Bootloader Heartbeat Request\n");
*DataBufPtr = 1;
BootloaderProtocolSendFrame(BOOTLOADER_HEARTBEAT_RESPONSE,1);
break;
}
case BOOTLOADER_ERASE_BOOTLOADER_FLASH_REQUEST:
{
printf("BOOTLOADER_ERASE_BOOTLOADER_FLASH_REQUEST\n");
BootloaderInterfaceStateMachine(BOOTLOADER_NEW_CMD_EVENT,BOOTLOADER_SM_ERASE_FLASH_CMD);
break;
}
case BOOTLOADER_INIT_UPLOAD_REQUEST:
{
printf("BOOTLOADER_INIT_UPLOAD_REQUEST\n");
BootloaderInterfaceStateMachine(BOOTLOADER_NEW_CMD_EVENT,BOOTLOADER_SM_INIT_UPLOAD_CMD);
break;
}
case BOOTLOADER_GET_STATE_REQUEST:
{
printf("BOOTLOADER_GET_STATE_REQUEST\n");
BootloaderProtocolSendBootloaderState((char)BootloaderInterfaceState);
break;
}
case BOOTLOADER_SEND_DATA_CHUNK_REQUEST:
{
// printf("BOOTLOADER_SEND_DATA_CHUNK_REQUEST\n");
BootloaderInterfaceStateMachine(BOOTLOADER_NEW_CMD_EVENT,BOOTLOADER_SM_NEW_DATA_CHUNK_CMD);
break;
}
case BOOTLOADER_UPLOAD_FINISHED_REQUEST:
{
printf("BOOTLOADER_UPLOAD_FINISHED_REQUEST\n");
BootloaderInterfaceStateMachine(BOOTLOADER_NEW_CMD_EVENT,BOOTLOADER_SM_UPLOAD_FINISHED_CMD);
break;
}
case BOOTLOADER_EXECUTE_UPGRAGE_REQUEST:
{
printf("BOOTLOADER_EXECUTE_UPGRAGE_REQUEST\n");
BootloaderInterfaceStateMachine(BOOTLOADER_NEW_CMD_EVENT,BOOTLOADER_SM_EXECUTE_UPGRAGE_CMD);
break;
}
case BOOTLOADER_ABORT_OPERATION_REQUEST:
{
printf("BOOTLOADER_ABORT_OPERATION_REQUEST\n");
BootloaderInterfaceStateMachine(BOOTLOADER_NEW_CMD_EVENT,BOOTLOADER_SM_ABORT_CMD);
}
case BOOTLOADER_CHECK_FLASH_FIRMW_INTEGRITY_REQUEST:
{
printf("BOOTLOADER_CHECK_FLASH_FIRMW_INTEGRITY_REQUEST\n");
BootloaderInterfaceStateMachine(BOOTLOADER_NEW_CMD_EVENT,BOOTLOADER_SM_CHECK_FLASH_CMD);
break;
}
case BOOTLOADER_GET_STORED_FIRMWARE_INFO_REQUEST:
{
printf("BOOTLOADER_CHECK_FLASH_FIRMW_INTEGRITY_REQUEST\n");
BootloaderInterfaceStateMachine(BOOTLOADER_NEW_CMD_EVENT,BOOTLOADER_SM_GET_FIRMWARE_DATA_CMD);
break;
}
default:
{
break;
}
}
}
void BootloaderCRCError(char Cmd, int RxCRC, int ExpectedCRC)
{
printf("BootloaderProtocol detected a CRC error. Cmd: %d, RxCRC:0x%x, Expected:[0x%x]\n",Cmd,RxCRC,ExpectedCRC);
BootloaderInterfaceStateMachine(BOOTLOADER_NEW_CMD_EVENT,BOOTLOADER_SM_INVALID_CRC_CMD);
}
void BootloaderInterfaceStateMachine(int Event, int Param)
{
switch(BootloaderInterfaceState)
{
case BOOTLOADER_STANDBY_STATE:
{
switch(Event)
{
case BOOTLOADER_TICK_EVENT:
{
break;
}
case BOOTLOADER_NEW_CMD_EVENT:
{
if(Param == BOOTLOADER_SM_ACTIVATE_CMD)
{
BootloaderInterfaceState = BOOTLOADER_ACTIVE_STATE;
printf("Bootloader Interface going into active state\n");
}
break;
}
case BOOTLOADER_TIMEOUT_EVENT:
{
break;
}
}
break;
}
case BOOTLOADER_ACTIVE_STATE:
{
switch(Event)
{
case BOOTLOADER_TICK_EVENT:
{
break;
}
case BOOTLOADER_NEW_CMD_EVENT:
{
switch(Param)
{
case BOOTLOADER_SM_ERASE_FLASH_CMD:
{
ResetBootloaderFlashEraseStateMachine(); //Setup the state machine
BootloaderProtocolSendACK(BOOTLOADER_ERASE_BOOTLOADER_FLASH_RESPONSE);
BootloaderInterfaceState = BOOTLOADER_ERASE_FLASH_STATE;
printf("Bootloader Interface going into Erase Flash state\n");
break;
}
case BOOTLOADER_SM_INIT_UPLOAD_CMD:
{
if(BootloaderFlashErased == 0)
{
BootloaderProtocolSendInitUploadResponse(BOOTLOADEDR_INIT_TRANSFER_ERROR_FLASH_NOT_ERASED);
}
else
{
BootloaderProtocolSendInitUploadResponse(BOOTLOADEDR_INIT_TRANSFER_OK);
//TODO: Shall we prepare something before??
BootloaderProtocolSendACK(BOOTLOADER_READY_FOR_DATA_RESPONSE);
BootloaderInterfaceState = BOOTLOADER_RECEIVING_FIRMWARE_STATE;
printf("Bootloader Interface going into Firmware RX state\n");
}
break;
}
case BOOTLOADER_SM_ABORT_CMD:
{
//TODO invalidate data in Flash
printf("Aborting upload, going into STANDBY mode\n");
BootloaderResetStateMachine();
break;
}
case BOOTLOADER_SM_EXECUTE_UPGRAGE_CMD:
{
if(BootloaderCheckFlashBootloaderData() == RET_OK)
{
BootloaderProtocolSendACK(BOOTLOADER_EXECUTE_UPGRADE_RESPONSE);
printf("Bootloader will now upgrade and reboot!!\n");
char Flags[2];
Flags[BOOTLOADER_FLAGS_ACTION_FLAG_INDEX] = BOOTLOADER_ACTION_FLASH_FIRMWARE_VALUE;
Flags[BOOTLOADER_FLAGS_ACTION_VALIDATOR_INDEX] = BOOTLOADER_FLASH_FIRMWARE_VALIDATOR;
SPIFlashWriteBuffer(Flags,2,FLASH_BTLDR_FLAGS_ADDRESS);
Sleep(100);
TurnOFFWiFi();
Sleep(100);
SoftReset();
}
else
{
BootloaderProtocolSendNACK(BOOTLOADER_EXECUTE_UPGRADE_RESPONSE);
printf("Bootloader upgrade request denied: Firmware not uploaded\n");
}
break;
}
case BOOTLOADER_SM_CHECK_FLASH_CMD:
{
if(BootloaderCheckFlashBootloaderData() == RET_OK)
{
BootloaderProtocolSendFlashCheckResult(FLASH_CHECK_SUCCESS);
}
else
{
BootloaderProtocolSendFlashCheckResult(FLASH_CHECK_FAILED);
}
break;
}
case BOOTLOADER_SM_GET_FIRMWARE_DATA_CMD:
{
char Response[21];
memset(Response,0xFF,sizeof(Response));
if(BootloaderCheckFlashBootloaderData() != RET_OK)
{
Response[0] = 0;
}
else
{
Response[0] = 1;
BootloaderIntToBytes(&Response[1],mStoredBootloaderInfo.Firmwareflags);
BootloaderIntToBytes(&Response[5],mStoredBootloaderInfo.NbRecords);
BootloaderIntToBytes(&Response[9],mStoredBootloaderInfo.FirmwareSize);
BootloaderIntToBytes(&Response[13],mStoredBootloaderInfo.Versioncode);
BootloaderIntToBytes(&Response[17],mStoredBootloaderInfo.DataCRC32);
}
BootloaderProtocolSendStoredFirmwareInfoResponse(Response,sizeof(Response));
break;
}
default:
{
//SEND NACK
BootloaderProtocolSendNACK(Param);
break;
}
}
break;
}
case BOOTLOADER_TIMEOUT_EVENT:
{
break;
}
}
break;
}
case BOOTLOADER_ERASE_FLASH_STATE:
{
switch(Event)
{
case BOOTLOADER_TICK_EVENT:
{
int res = BootloaderFlashEraseStateMachine(BOOTLOADER_FLASH_ERASE_SM_TICK_EVENT);
switch(res)
{
case BOOTLOADER_FLASH_ERASE_RUNNING_RES:
{
break;
}
case BOOTLOADER_FLASH_ERASE_FINISHED_RES:
{
printf("Flash erase finished. Bootloader Interface going into Active state\n");
BootloaderProtocolSendACK(BOOTLOADER_ERASE_BOOTLOADER_FLASH_RESULT_RESPONSE); //TODO: send result instead
BootloaderInterfaceState = BOOTLOADER_ACTIVE_STATE;
BootloaderFlashErased = 1;
break;
}
case BOOTLOADER_FLASH_ERASE_ERROR_RES:
{
printf("Flash erase error. Bootloader Interface going into Active state\n");
BootloaderProtocolSendNACK(BOOTLOADER_ERASE_BOOTLOADER_FLASH_RESULT_RESPONSE); //TODO: send result instead
BootloaderInterfaceState = BOOTLOADER_ACTIVE_STATE;
break;
}
case BOOTLOADER_FLASH_ERASE_ABORT_RES:
{
printf("Flash erase abort. Bootloader Interface going into Active state\n");
BootloaderProtocolSendNACK(BOOTLOADER_ERASE_BOOTLOADER_FLASH_RESULT_RESPONSE); //TODO: send result instead
BootloaderInterfaceState = BOOTLOADER_ACTIVE_STATE;
break;
}
}
break;
}
case BOOTLOADER_NEW_CMD_EVENT:
{
switch(Param)
{
case BOOTLOADER_SM_ABORT_CMD:
{
//TODO: stop erasing and reset SM.
//TODO invalidate data in Flash
BootloaderFlashEraseStateMachine(BOOTLOADER_FLASH_ERASE_SM_ABORT_EVENT);
printf("Aborting Flash erase, going into STANDBY mode\n");
BootloaderResetStateMachine();
break;
}
default:
{
//SEND NACK
BootloaderProtocolSendNACK(Param);
break;
}
}
break;
}
case BOOTLOADER_TIMEOUT_EVENT:
{
break;
}
}
break;
}
case BOOTLOADER_RECEIVING_FIRMWARE_STATE:
{
switch(Event)
{
case BOOTLOADER_TICK_EVENT:
{
int res = BootloaderFlashWriteStateMachine(BOOTLOADER_FLASH_WRITE_SM_TICK_EVENT);
switch(res)
{
case BOOTLOADER_FLASH_WRITING_RES:
{
break;
}
case BOOTLOADER_FLASH_WRITE_FINISHED_RES:
{
BootloaderProtocolSendDataChunkResult(BOOTLOADER_CHUNK_TRANSFER_SUCCESS,CurDataChunkIndex);
printf("Bootloader Chunk %d successfuly written to flash\n",CurDataChunkIndex);
CurDataChunkIndex++;
break;
}
case BOOTLOADER_FLASH_WRITE_ERROR_RES:
{
BootloaderProtocolSendDataChunkResult(BOOTLOADER_CHUNK_TRANSFER_ERROR_FLASH_ERROR,CurDataChunkIndex);
BootloaderResetStateMachine();
printf("Bootloader Flash write error. Aborting and going into STANDBY state\n");
break;
}
case BOOTLOADER_FLASH_WRITE_ABORT_RES:
{
break;
}
}
break;
}
case BOOTLOADER_NEW_CMD_EVENT:
{
switch(Param)
{
case BOOTLOADER_SM_NEW_DATA_CHUNK_CMD:
{
//TODO:Check data validity
//TODO: Write data to flash
//Extract index from buffer
unsigned int DataChunkIndex = 0;
unsigned int DataChunkSize = 0;
DataChunkSize = 0;
// DataChunkIndex = BootloaderBuffer[0];
// DataChunkIndex <<= 8;
// DataChunkIndex += BootloaderBuffer[1];
// DataChunkIndex <<= 8;
// DataChunkIndex += BootloaderBuffer[2];
// DataChunkIndex <<= 8;
// DataChunkIndex += BootloaderBuffer[3];
DataChunkIndex = BootloaderBytesToInt(&BootloaderBuffer[0]);
// DataChunkSize = BootloaderBuffer[4];
// DataChunkSize <<= 8;
// DataChunkSize += BootloaderBuffer[5];
// DataChunkSize <<= 8;
// DataChunkSize += BootloaderBuffer[6];
// DataChunkSize <<= 8;
// DataChunkSize += BootloaderBuffer[7];
DataChunkSize = BootloaderBytesToInt(&BootloaderBuffer[4]);
BootloaderFlashWriteDataPtr = &BootloaderBuffer[8];
//Check CRC
if(CurDataChunkIndex != DataChunkIndex)
{
//Error... abort.
BootloaderProtocolSendDataChunkResult(BOOTLOADER_CHUNK_TRANSFER_ERROR_INVALID_CHUNK_INDEX,CurDataChunkIndex);
printf("Bootloader Interface ABORTING UPLOAD. Received invalid chunk index. Rx: [%d] - Expected: [%d]\n", DataChunkIndex,CurDataChunkIndex);
ResetBootloaderFlashWriteStateMachine();
}
else
{
CurDataChunkSize = DataChunkSize;
BootloaderFlashWriteStateMachine(BOOTLOADER_FLASH_WRITE_SM_NEW_BUFFER_EVENT);
printf("Bootloader Interface. Rx new data chunk. Writing to flash. Index: %d\n", DataChunkIndex);
}
break;
}
case BOOTLOADER_SM_INVALID_CRC_CMD:
{
//BootloaderProtocol determined the CRC of the chunk was invalid.
BootloaderProtocolSendDataChunkResult(BOOTLOADER_CHUNK_TRANSFER_ERROR_RESEND,CurDataChunkIndex);
printf("Bootloader Interface invalid chunk CRC. Requesting resend chunk index [%d]\n", CurDataChunkIndex);
break;
}
case BOOTLOADER_SM_UPLOAD_FINISHED_CMD:
{
printf("Bootloader Interface firmware upload finished. Check flash integrity.\n");
if(BootloaderCheckFlashBootloaderData() == RET_OK)
{
BootloaderInterfaceState = BOOTLOADER_ACTIVE_STATE;
//BootloaderProtocolSendACK(BOOTLOADER_UPLOAD_FINISHED_RESPONSE);
BootloaderProtocolSendFirmwareUploadResult(BOOTLOADER_UPLOAD_SUCCESS);
FirmwareUploaded = 1;
}
else
{
printf("Firmware integrity check failed. Going back to STANDBY state.\n");
// BootloaderProtocolSendNACK(BOOTLOADER_UPLOAD_FINISHED_RESPONSE);
BootloaderProtocolSendFirmwareUploadResult(BOOTLOADER_UPLOAD_FAILED_FLASH_VERIFICATION_ERROR);
BootloaderResetStateMachine();
FirmwareUploaded = 0;
}
break;
}
case BOOTLOADER_SM_ABORT_CMD:
{
//TODO invalidate data in Flash
printf("Bootloader aborting firmware download. Going back to STANDBY state\n");
BootloaderFlashWriteStateMachine(BOOTLOADER_FLASH_WRITE_SM_ABORT_EVENT);
BootloaderResetStateMachine();
break;
}
default:
{
//WHAT TO DO???
break;
}
}
break;
}
case BOOTLOADER_TIMEOUT_EVENT:
{
break;
}
}
break;
}
case BOOTLOADER_SENDING_FIRMWARE_COPY_STATE:
{
switch(Event)
{
case BOOTLOADER_TICK_EVENT:
{
break;
}
case BOOTLOADER_NEW_CMD_EVENT:
{
switch(Param)
{
case BOOTLOADER_SM_ABORT_CMD:
{
//TODO invalidate data in Flash
printf("Aborting upload, going into STANDBY mode\n");
BootloaderResetStateMachine();
break;
}
default:
{
//SEND NACK
BootloaderProtocolSendNACK(Param);
break;
}
}
break;
}
case BOOTLOADER_TIMEOUT_EVENT:
{
break;
}
}
break;
}
case BOOTLOADER_PRINTING_FIRMWARE_STATE:
{
switch(Event)
{
case BOOTLOADER_TICK_EVENT:
{
break;
}
case BOOTLOADER_NEW_CMD_EVENT:
{
switch(Param)
{
case BOOTLOADER_SM_ABORT_CMD:
{
//TODO invalidate data in Flash
printf("Aborting upload, going into STANDBY mode\n");
BootloaderResetStateMachine();
break;
}
default:
{
//SEND NACK
BootloaderProtocolSendNACK(Param);
break;
}
}
break;
}
case BOOTLOADER_TIMEOUT_EVENT:
{
break;
}
}
break;
}
}
}
void BootloaderResetStateMachine()
{
BootloaderInterfaceState = BOOTLOADER_STANDBY_STATE;
DataChunkWritten = 0;
CurDataChunkIndex = 0;
FirmwareUploaded = 0;
CurDataChunkIndex = 0;
FirmwareUploaded = 0;
CurDataChunkSize = 0;
ResetBootloaderFlashEraseStateMachine();
ResetBootloaderFlashWriteStateMachine();
CloseBootloaderServer();
}
void BootloaderActivateBootloader()
{
OpenBootloaderServer();
BootloaderInterfaceStateMachine(BOOTLOADER_NEW_CMD_EVENT,BOOTLOADER_SM_ACTIVATE_CMD);
}
void BootloaderDeactivateBootloader()
{
BootloaderResetStateMachine();
// CloseBootloaderServer();
// BootloaderIterfaceStateMachine(BOOTLOADER_SM_ABORT_CMD,0);
}
int BootloaderFlashEraseStateMachine(int event)
{
if(event == BOOTLOADER_FLASH_ERASE_SM_ABORT_EVENT)
{
ResetBootloaderFlashEraseStateMachine();
return BOOTLOADER_FLASH_ERASE_ABORT_RES;
}
switch(BooloaderFlashEraseState)
{
case BOOTLOADER_FLASH_ERASE_SECTOR_STATE:
{
if(SPIFlashErase64KSector(BootloaderCurFlashEraseAddress,0) == RET_ERROR)
{
printf("Bootloader Interface Erasing sector %0x%x\n", BootloaderCurFlashEraseAddress);
BooloaderFlashEraseState = BOOTLOADER_FLASH_ERASE_ERROR_STATE;
return BOOTLOADER_FLASH_ERASE_ERROR_RES;
}
BooloaderFlashErasePollCount = 0;
TimerStart(BOOTLOADER_FLASH_POLL_TIMER,BOOTLOADER_FLASH_ERASE_POLL_TIMEOUT);
BooloaderFlashEraseState = BOOTLOADER_FLASH_ERASE_WAIT_FOR_SECTOR_DONE;
break;
}
case BOOTLOADER_FLASH_ERASE_WAIT_FOR_SECTOR_DONE:
{
if(IsTimerExpired(BOOTLOADER_FLASH_POLL_TIMER) == 1)
{
if(SPIFlashCheckBusy() == 0) //sector erased
{
if(BootloaderCurFlashEraseAddress == FLASH_BTLDR_FIRMWARE_LAST_64K_SECTOR_ADD)
{
//Whole bootloader partition is erased.
printf("Bootloader Interface: Last sector 0x%x erased after %d polls\n",BootloaderCurFlashEraseAddress,BooloaderFlashErasePollCount);
BooloaderFlashEraseState = BOOTLOADER_FLASH_ERASE_FINISHED_STATE;
return BOOTLOADER_FLASH_ERASE_FINISHED_RES;
break;
}
else
{
printf("Bootloader Interface sector 0x%x erased after %d polls\n",BootloaderCurFlashEraseAddress,BooloaderFlashErasePollCount);
BootloaderCurFlashEraseAddress += SPI_FLASH_64K_SECTOR_SIZE;
BooloaderFlashEraseState = BOOTLOADER_FLASH_ERASE_SECTOR_STATE;
}
}
else
{
if(BooloaderFlashErasePollCount >= BOOTLOADER_FLASH_ERASE_MAX_POLL_COUNT)
{
printf("Bootloader Interface Flash erase error. Max poll count reached : %d!!!\n",BooloaderFlashErasePollCount);
BooloaderFlashEraseState = BOOTLOADER_FLASH_ERASE_ERROR_STATE;
return BOOTLOADER_FLASH_ERASE_ERROR_RES;
}
else
{
TimerStart(BOOTLOADER_FLASH_POLL_TIMER,BOOTLOADER_FLASH_ERASE_POLL_TIMEOUT);
BooloaderFlashErasePollCount++;
}
}
}
break;
}
case BOOTLOADER_FLASH_ERASE_CHECKBACK_STATE:
{
break;
}
case BOOTLOADER_FLASH_ERASE_FINISHED_STATE:
{
return BOOTLOADER_FLASH_ERASE_FINISHED_RES;
break;
}
case BOOTLOADER_FLASH_ERASE_ERROR_STATE:
{
return BOOTLOADER_FLASH_ERASE_ERROR_RES;
break;
}
}
return BOOTLOADER_FLASH_ERASE_RUNNING_RES;
}
int ResetBootloaderFlashEraseStateMachine()
{
BooloaderFlashEraseState = BOOTLOADER_FLASH_ERASE_SECTOR_STATE;
BootloaderCurFlashEraseAddress = FLASH_BTLDR_FIRMWARE_START_ADDRESS;
BooloaderFlashErasePollCount = 0;
BootloaderFlashErased = 0;
}
int BootloaderFlashWriteStateMachine(int event)
{
switch(BootloaderFlashWriteState)
{
case BOOTLOADER_FLASH_WRITE_STANDBY_STATE:
{
if(event == BOOTLOADER_FLASH_WRITE_SM_TICK_EVENT)
{
//TODO: timeout
// return BOOTLOADER_FLASH_WRITE_ERROR_RES;
}
else if(event == BOOTLOADER_FLASH_WRITE_SM_NEW_BUFFER_EVENT)
{
// printf("Starting writing data to Flash\nFlash Address : Data\n");
BootloaderFlashWriteState = BOOTLOADER_FLASH_WRITE_BUFFER_STATE;
BootloaderFirmwareChunkWriteCount = 0;
return BOOTLOADER_FLASH_WRITING_RES;
}
break;
}
case BOOTLOADER_FLASH_WRITE_BUFFER_STATE:
{
if(BootloaderFlashWriteDataPtr == 0)
{
ResetBootloaderFlashWriteStateMachine();
return BOOTLOADER_FLASH_WRITE_ERROR_RES;
}
while(BootloaderFirmwareChunkWriteCount < CurDataChunkSize)
{
//printf("%d : 0x%x\n",(BootloaderCurFlashWriteAddress-FLASH_BTLDR_FIRMWARE_START_ADDRESS),(unsigned int)*BootloaderFlashWriteDataPtr);
if(SPIFlashWriteByte(BootloaderCurFlashWriteAddress++,*BootloaderFlashWriteDataPtr++,1) == RET_ERROR)
{
printf("Bootloader flash error. Aborting and going back to STANDBY\n");
BootloaderFlashWriteState = BOOTLOADER_FLASH_WRITE_ERROR_STATE;
return BOOTLOADER_FLASH_WRITE_ERROR_RES;
}
int cnt = 0;
while(1)
{
if(SPIFlashCheckBusy() == 0)
{
break;
}
if(cnt++ > 200)
{
printf("Bootloader flash write timeout error. Aborting and going back to STANDBY\n");
BootloaderFlashWriteState = BOOTLOADER_FLASH_WRITE_ERROR_STATE;
return BOOTLOADER_FLASH_WRITE_ERROR_RES;
}
}
BootloaderFirmwareChunkWriteCount++;
}
BootloaderFlashWriteState = BOOTLOADER_FLASH_WRITE_WAIT_FOR_BYTE_DONE;
return BOOTLOADER_FLASH_WRITING_RES;
// BootloaderFlashWriteState = BOOTLOADER_FLASH_WRITE_STANDBY_STATE;
// return BOOTLOADER_FLASH_WRITE_FINISHED_RES;
break;
}
case BOOTLOADER_FLASH_WRITE_WAIT_FOR_BYTE_DONE:
{
if(event == BOOTLOADER_FLASH_WRITE_SM_TICK_EVENT)
{
BootloaderFlashWriteState = BOOTLOADER_FLASH_WRITE_STANDBY_STATE;
return BOOTLOADER_FLASH_WRITE_FINISHED_RES;
// if(SyslogIsBufferEmpty() == RET_OK)
// {
// BootloaderFlashWriteState = BOOTLOADER_FLASH_WRITE_STANDBY_STATE;
// return BOOTLOADER_FLASH_WRITE_FINISHED_RES;
// }
// else
// {
// return BOOTLOADER_FLASH_WRITING_RES;
// }
}
break;
}
case BOOTLOADER_FLASH_WRITE_CHECKBACK_STATE:
{
break;
}
case BOOTLOADER_FLASH_WRITE_FINISHED_STATE:
{
return BOOTLOADER_FLASH_WRITE_FINISHED_RES;
break;
}
case BOOTLOADER_FLASH_WRITE_ERROR_STATE:
{
return BOOTLOADER_FLASH_WRITE_ERROR_RES;
break;
}
}
}
int BootloaderPrintFlashData()
{
}
int BootloaderCheckFlashBootloaderData()
{
unsigned char FlashData[700];
unsigned int FlashAddress = FLASH_BTLDR_FIRMWARE_START_ADDRESS;
unsigned int FileHeaderCode, FirmwareFlags, NbRecords, FirmwareSize, VersionCode, CRC32;
unsigned int ComputedCRC32 = CRC_START_32;
//SPIFlashReadBuffer(FlashData,700,FlashAddress);
printf("Checking Flash bootloader data integrity... \n");
SPIFlashReadBuffer(FlashData,FLASH_BTLDR_HEADER_SIZE,FlashAddress);
FileHeaderCode = BootloaderBytesToInt(FlashData);
FirmwareFlags = BootloaderBytesToInt(&FlashData[4]);
NbRecords = BootloaderBytesToInt(&FlashData[8]);
FirmwareSize = BootloaderBytesToInt(&FlashData[12]);
VersionCode = BootloaderBytesToInt(&FlashData[16]);
CRC32 = BootloaderBytesToInt(&FlashData[20]);
mStoredBootloaderInfo.Firmwareflags = FirmwareFlags;
mStoredBootloaderInfo.NbRecords = NbRecords;
mStoredBootloaderInfo.FirmwareSize = FirmwareSize;
mStoredBootloaderInfo.Versioncode = VersionCode;
mStoredBootloaderInfo.DataCRC32 = CRC32;
//printf("File Header: Code:[0x%x] - Flags:[0x%x] - Nb Records:[%d] - Firmware Size:[%d] - Version:[0x%x] - CRC32:[0x%x]\n",FileHeaderCode,FirmwareFlags,NbRecords,FirmwareSize,VersionCode,CRC32);
if(FileHeaderCode != BOOTLOADER_FILE_HEADER_CODE)
{
// printf("Invalid file header code, aborting\n");
return RET_ERROR;
}
if(NbRecords == 0)
{
// printf("No records in file (NbRecords = 0), aborting\n");
return RET_ERROR;
}
FlashAddress += FLASH_BTLDR_HEADER_SIZE; //point to the start of bootloader data
int CurRecord = 0;
bool Done = false;
int RecHeader, RecSize, RecStartAddress;
//Check the header of each sector.
while(Done == false)
{
SPIFlashReadBuffer(FlashData,12,FlashAddress);
RecHeader = BootloaderBytesToInt(FlashData);
RecSize = BootloaderBytesToInt(&FlashData[4]);
RecStartAddress = BootloaderBytesToInt(&FlashData[8]);
FlashAddress += 12;
if(RecHeader != BOOTLOADER_RECORD_HEADER_CODE)
{
// printf("Error in record #%d. Invalid header code : [0x%x]\n",CurRecord,RecHeader);
return RET_ERROR;
}
if(RecSize == 0)
{
// printf("Error in record #%d. Invalid record size (RecordSize = 0) \n");
return RET_ERROR;
}
// printf("Record #%d OK! Header:[0x%x] - Size:[%d] - Start Address:[0x%x]\n",CurRecord,RecHeader,RecSize,RecStartAddress);
// while(SyslogIsBufferEmpty() == RET_ERROR)
// {
// SyslogTick();
// TickWiFi();
// }
CurRecord++;
if(CurRecord == NbRecords)
{
// Done = true;
// printf("All records checked OK! Computing CRC...\n");
Done = true;
break;
//return RET_OK;
}
else
{
FlashAddress += RecSize;
}
}
//Now, compute whole data CRC
FlashAddress = FLASH_BTLDR_FIRMWARE_START_ADDRESS + FLASH_BTLDR_HEADER_SIZE;
char Byte;
int i;
for(i = 0; i < FirmwareSize; i++)
{
SPIFlashReadBuffer(&Byte,1,FlashAddress++);
ComputedCRC32 = update_crc_32(ComputedCRC32,Byte);
}
ComputedCRC32 ^= 0xffffffffL;
if(ComputedCRC32 == CRC32)
{
// printf("CRC32 matches. Computed:[0x%x] - Expected:[0x%x]\n",ComputedCRC32,CRC32);
// printf("Flash check success. Firmware is valid\n");
return RET_OK;
}
else
{
// printf("CRC32 mismatch. Computed:[0x%x] - Expected:[0x%x]\n",ComputedCRC32,CRC32);
// printf("Flash check failed.\n");
return RET_ERROR;
}
return RET_OK;
}
int ResetBootloaderFlashWriteStateMachine()
{
BootloaderFlashWriteState = BOOTLOADER_FLASH_WRITE_STANDBY_STATE;
BootloaderCurFlashWriteAddress = FLASH_BTLDR_FIRMWARE_START_ADDRESS;
BootloaderFlashWritePollCount = 0;
BootloaderFirmwareChunkWriteCount = 0;
BootloaderFlashWriteDataPtr = 0;
BootloaderFirmwareChunkWriteCount = 0;
return RET_OK;
}
int BootloaderBytesToInt(unsigned char *Bytes)
{
if(Bytes == 0)
{
return 0;
}
int Output = Bytes[0];
Output <<= 8;
Output += Bytes[1];
Output <<= 8;
Output += Bytes[2];
Output <<= 8;
Output += Bytes[3];
return Output;
}
int BootloaderIntToBytes(unsigned char *Buf, unsigned int Input)
{
if(Buf == 0)
{
return 0;
}
Buf[3] = (unsigned char)(Input & 0xFF);
Input >>= 8;
Buf[2] = (unsigned char)(Input & 0xFF);
Input >>= 8;
Buf[1] = (unsigned char)(Input & 0xFF);
Input >>= 8;
Buf[0] = (unsigned char)(Input & 0xFF);
Input >>= 8;
return 1;
}
+182
View File
@@ -0,0 +1,182 @@
/*
* File: ChaletPowerRelay.h
* Author: JF
*
* Created on November 30, 2018, 7:33 PM
*/
#ifndef BOOTLOADERINTERFACE_H
#define BOOTLOADERINTERFACE_H
#include "define.h"
#define BOOTLOADER_FILE_HEADER_CODE (int)0xBAADBEEF
#define BOOTLOADER_RECORD_HEADER_CODE (int)0xDEADBEEF
#define BOOTLOADER_FLASH_FIRMWARE_VALIDATOR 0xA8
#define BOOTLOADER_ENTER_UPLOAD_MODE_VALIDATOR 0x5A
typedef struct
{
unsigned char BootloaderAction;
unsigned char BootloaderActionValidator;
}stBootloaderFlags_t;
typedef struct
{
unsigned int Firmwareflags;
unsigned int NbRecords;
unsigned int FirmwareSize;
unsigned int Versioncode;
unsigned int DataCRC32;
}stStoredBootloaderInfo;
extern stBootloaderFlags_t mBootloaderFlags;
stStoredBootloaderInfo mStoredBootloaderInfo;
enum eBootloaderFlagsIndex
{
BOOTLOADER_FLAGS_ACTION_FLAG_INDEX = 0,
BOOTLOADER_FLAGS_ACTION_VALIDATOR_INDEX,
BOOTLOADER_FLAGS_MAX_INDEX = 12
};
enum eBootloaderActionFlagValues
{
BOOTLOADER_ACTION_JUMP_TO_APP_VALUE = 0,
BOOTLOADER_ACTION_FLASH_FIRMWARE_VALUE = 1,
BOOTLOADER_ACTION_ENTER_UPDATE_MODE_VALUE = 2,
BOOTLOADER_ACTION_MAX_VALUE
};
enum eBootloaderStates
{
BOOTLOADER_STANDBY_STATE,
BOOTLOADER_ACTIVE_STATE,
BOOTLOADER_ERASE_FLASH_STATE,
BOOTLOADER_RECEIVING_FIRMWARE_STATE,
BOOTLOADER_SENDING_FIRMWARE_COPY_STATE,
BOOTLOADER_PRINTING_FIRMWARE_STATE,
BOOTLOADER_MAX_STATE
};
enum eBootloaderStateMachineEvents
{
BOOTLOADER_TICK_EVENT,
BOOTLOADER_NEW_CMD_EVENT,
BOOTLOADER_TIMEOUT_EVENT,
BOOTLOADER_MAX_EVENT
};
enum eBootloaderFlashEraseStates
{
BOOTLOADER_FLASH_ERASE_SECTOR_STATE,
BOOTLOADER_FLASH_ERASE_WAIT_FOR_SECTOR_DONE,
BOOTLOADER_FLASH_ERASE_CHECKBACK_STATE,
BOOTLOADER_FLASH_ERASE_FINISHED_STATE,
BOOTLOADER_FLASH_ERASE_ERROR_STATE,
BOOTLOADER_FLASH_ERASE_MAX_STATE
};
enum eBootloaderFlashEraseResults
{
BOOTLOADER_FLASH_ERASE_RUNNING_RES,
BOOTLOADER_FLASH_ERASE_FINISHED_RES,
BOOTLOADER_FLASH_ERASE_ERROR_RES,
BOOTLOADER_FLASH_ERASE_ABORT_RES,
BOOTLOADER_FLASH_ERASE_MAX_RES
};
enum eBootloaderFlahsEraseSMEvents
{
BOOTLOADER_FLASH_ERASE_SM_TICK_EVENT,
BOOTLOADER_FLASH_ERASE_SM_ABORT_EVENT,
BOOTLOADER_FLASH_ERASE_SM_MAX_EVENT
};
enum eBootloaderFlashWriteStates
{
BOOTLOADER_FLASH_WRITE_STANDBY_STATE,
BOOTLOADER_FLASH_WRITE_BUFFER_STATE,
BOOTLOADER_FLASH_WRITE_WAIT_FOR_BYTE_DONE,
BOOTLOADER_FLASH_WRITE_CHECKBACK_STATE,
BOOTLOADER_FLASH_WRITE_FINISHED_STATE,
BOOTLOADER_FLASH_WRITE_ERROR_STATE,
BOOTLOADER_FLASH_WRITE_MAX_STATE
};
enum eBootloaderFlashWriteResults
{
BOOTLOADER_FLASH_WRITING_RES,
BOOTLOADER_FLASH_WRITE_FINISHED_RES,
BOOTLOADER_FLASH_WRITE_ERROR_RES,
BOOTLOADER_FLASH_WRITE_ABORT_RES,
BOOTLOADER_FLASH_WRITE_MAX_RES
};
enum eBootloaderFlahsWriteSMEvents
{
BOOTLOADER_FLASH_WRITE_SM_TICK_EVENT,
BOOTLOADER_FLASH_WRITE_SM_NEW_BUFFER_EVENT,
BOOTLOADER_FLASH_WRITE_SM_ABORT_EVENT,
BOOTLOADER_FLASH_WRITE_SM_MAX_EVENT
};
enum eBootloaderStateMachineCmds
{
BOOTLOADER_SM_ACTIVATE_CMD,
BOOTLOADER_SM_ABORT_CMD,
BOOTLOADER_SM_ERASE_FLASH_CMD,
BOOTLOADER_SM_INIT_UPLOAD_CMD,
BOOTLOADER_SM_NEW_DATA_CHUNK_CMD,
BOOTLOADER_SM_UPLOAD_FINISHED_CMD,
BOOTLOADER_SM_EXECUTE_UPGRAGE_CMD,
BOOTLOADER_SM_INVALID_CRC_CMD,
BOOTLOADER_SM_CHECK_FLASH_CMD,
BOOTLOADER_SM_GET_FIRMWARE_DATA_CMD
};
extern unsigned char BootloaderBuffer[300];
int BootloaderInterfaceInit();
void BootloaderExecuteCmd(char Cmd,bool CRCValid);
void BootloaderCRCError(char Cmd, int RxCRC, int ExpectedCRC);
void BootloaderInterfaceTick();
void BootloaderInterfaceStateMachine(int Event, int Param);
void BootloaderResetStateMachine();
void BootloaderActivateBootloader();
void BootloaderDeactivateBootloader();
int BootloaderFlashEraseStateMachine(int event);
int ResetBootloaderFlashEraseStateMachine();
int BootloaderFlashWriteStateMachine(int event);
int ResetBootloaderFlashWriteStateMachine();
int BootloaderCheckFlashBootloaderData();
int BootloaderPrintFlashData();
int BootloaderBytesToInt(unsigned char *Bytes);
int BootloaderIntToBytes(unsigned char *Buf, unsigned int Input);
#endif /* BOOTLOADERINTERFACE_H */
+427
View File
@@ -0,0 +1,427 @@
/**********************************************************************
Project: Automatic cat feeder
Date: march 19 2006
Author: Jean-Fran�ois Martel
Target: PIC 18F252
Compiler: Microchip mcc18
Filename: Protocol.c
File description: Communication protocol implementation.
jean-francois.martel@polymtl.ca
**********************************************************************/
#include "define.h"
#include <string.h>
#include "ProtocolDefs.h"
#include "BootloaderProtocol.h"
#include "BootloaderInterface.h"
#include "WiFiCtrl.h"
#include "checksum.h"
//test
unsigned int BootloaderHeader = 0;
unsigned int BootloaderDataSize = 0;
unsigned int BootloaderDataCtr = 0;
unsigned int BootloaderBufPtr = 0;
unsigned int BootloaderCRC = 0;
unsigned int BtldrComputedCRC = CRC_START_32;
unsigned char *BootloaderRxPtr;
unsigned char BootloaderCommand = 0;
unsigned char BootloaderState = RxHeader1;
const unsigned char *BootloaderDataStartPtr = &BootloaderBuffer[9];
static char MyDeviceID = ID_SPRINKLER_DEVICE;
void BootloaderProtocolInit(void)
{
BootloaderProtocolResetStateMachine();
}
void BootloaderProtocolStateMachine(unsigned char Data)
{
switch(BootloaderState)
{
case Initialization: //Reset all pointers and data...
{
BootloaderDataSize = 0;
BootloaderBufPtr = 0;
BootloaderCommand = 0;
BootloaderCRC = 0;
BootloaderState = RxHeader1;
BtldrComputedCRC = CRC_START_32;
break;
}
case RxHeader1: //Wait for data header...
{
BootloaderHeader <<= 8;
BootloaderHeader += Data; //0xDE
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
if(Data == BOOTLOADER_FRAME_HEADER_1)
{
BootloaderState = RxHeader2;
}
else
{
BootloaderProtocolResetStateMachine();
}
break;
}
case RxHeader2: //Wait for data header...
{
BootloaderHeader <<= 8;
BootloaderHeader += Data; //0xAD
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
if(Data == BOOTLOADER_FRAME_HEADER_2)
{
BootloaderState = RxHeader3;
}
else
{
BootloaderProtocolResetStateMachine();
}
break;
}
case RxHeader3: //Wait for data header...
{
BootloaderHeader <<= 8;
BootloaderHeader += Data; //0xBE
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
if(Data == BOOTLOADER_FRAME_HEADER_3)
{
BootloaderState = RxHeader4;
}
else
{
BootloaderProtocolResetStateMachine();
}
break;
}
case RxHeader4: //Wait for data header...
{
BootloaderHeader <<= 8;
BootloaderHeader += Data; //0xEF
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
if(BootloaderHeader != BOOTLOADER_FRAME_HEADER)
{
//TODO, send NACK?
BootloaderProtocolResetStateMachine();
break;
}
else
{
BootloaderState = RxCmd;
}
break;
}
case RxCmd:
{
BootloaderCommand = Data;
BootloaderState = RxPayloadSize1;
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
break;
}
case RxPayloadSize1:
{
BootloaderDataSize = Data;
BootloaderState = RxPayloadSize2;
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
break;
}
case RxPayloadSize2:
{
BootloaderDataSize <<= 8;
BootloaderDataSize += Data;
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
BootloaderState = RxPayloadSize3;
break;
}
case RxPayloadSize3:
{
BootloaderDataSize <<= 8;
BootloaderDataSize += Data;
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
BootloaderState = RxPayloadSize4;
break;
}
case RxPayloadSize4:
{
BootloaderDataSize <<= 8;
BootloaderDataSize += Data;
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
if(BootloaderDataSize > MAX_BOOTLOADER_PAYLOAD_SIZE+8) //+8 bytes for the size and index data
{
//TODO, send NACK?
BootloaderProtocolResetStateMachine();
break;
}
if(BootloaderDataSize == 0)
{
BootloaderState = RxCRC1;
}
else
{
BootloaderState = RxPayload;
}
break;
}
case RxPayload: //Data size
{
*BootloaderRxPtr = Data;
BootloaderRxPtr++;
BootloaderDataCtr++;
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
if(BootloaderDataCtr == BootloaderDataSize)
{
BootloaderState = RxCRC1;
break;
}
break;
}
case RxCRC1: //Data size
{
BootloaderCRC = Data;
BootloaderState = RxCRC2;
break;
}
case RxCRC2: //Data size
{
BootloaderCRC <<= 8;
BootloaderCRC += Data;
BootloaderState = RxCRC3;
break;
}
case RxCRC3: //Data size
{
BootloaderCRC <<= 8;
BootloaderCRC += Data;
BootloaderState = RxCRC4;
break;
}
case RxCRC4: //Data size
{
BootloaderCRC <<= 8;
BootloaderCRC += Data;
//TODO: Compute and Compare CRC.
BtldrComputedCRC ^= 0xffffffffL;
//if(BootloaderCRC != 0xBAADCAFE)
if(BootloaderCRC != BtldrComputedCRC)
{
BootloaderExecuteCmd(BootloaderCommand,0);
BootloaderProtocolResetStateMachine();
return;
}
BootloaderExecuteCmd(BootloaderCommand,1);
BootloaderProtocolResetStateMachine();
break;
}
default:
{
BootloaderProtocolResetStateMachine();
break;
}
}
}
void BootloaderProtocolProtocolAnalyzeNewData(unsigned char *DataBuf, int size)
{
int i;
for(i = 0; i < size; i++)
{
BootloaderProtocolStateMachine(*DataBuf++);
}
}
void BootloaderProtocolResetStateMachine()
{
BootloaderDataSize = 0;
BootloaderHeader = 0;
BootloaderBufPtr = 0;
BootloaderCommand = 0;
BootloaderCRC = 0;
BootloaderState = RxHeader1;
BootloaderDataCtr = 0;
BtldrComputedCRC = CRC_START_32;
BootloaderRxPtr = &BootloaderBuffer[0];
}
void BootloaderProtocolSendFrame(unsigned char Cmd, int Size)
{
//Header
BootloaderBuffer[0] = BOOTLOADER_FRAME_HEADER_1; //Header
BootloaderBuffer[1] = BOOTLOADER_FRAME_HEADER_2;
BootloaderBuffer[2] = BOOTLOADER_FRAME_HEADER_3;
BootloaderBuffer[3] = BOOTLOADER_FRAME_HEADER_4;
BootloaderBuffer[4] = Cmd;
char nibble = (char)((Size >> 24) &0x000000FF);
BootloaderBuffer[5] = nibble;
nibble = (char)((Size >> 16) &0x000000FF);
BootloaderBuffer[6] = nibble;
nibble = (char)((Size >> 8) &0x000000FF);
BootloaderBuffer[7] = nibble;
nibble = (char)(Size &0x000000FF);
BootloaderBuffer[8] = nibble;
unsigned int CRC = CRC_START_32;
CRC = crc_32((const unsigned char*)BootloaderBuffer,Size+9);
unsigned char* CRCPtr = (unsigned char*)BootloaderDataStartPtr + Size;
nibble = (char)((CRC >> 24) &0x000000FF);
*CRCPtr++ = nibble;
nibble = (char)((CRC >> 16) &0x000000FF);
*CRCPtr++ = nibble;
nibble = (char)((CRC >> 8) &0x000000FF);
*CRCPtr++ = nibble;
nibble = (char)(CRC &0x000000FF);
*CRCPtr++ = nibble;
// *CRCPtr++ = 0xBA;
// *CRCPtr++ = 0xAD;
// *CRCPtr++ = 0xCA;
// *CRCPtr++ = 0xFE;
SendBootloaderData(&BootloaderBuffer[0],Size + PROTOCOL_INFO_DATA_SIZE);
}
unsigned char *BootloaderProtocolGetDataBufferPtr()
{
return (unsigned char*)BootloaderDataStartPtr;
}
void BootloaderProtocolSendHeartbeat()
{
*BootloaderProtocolGetDataBufferPtr() = BOOTLOADER_ACK;
BootloaderProtocolSendFrame(BOOTLOADER_HEARTBEAT_RESPONSE,1);
}
void BootloaderProtocolSendACK(unsigned char Cmd)
{
*BootloaderProtocolGetDataBufferPtr() = BOOTLOADER_ACK;
BootloaderProtocolSendFrame(Cmd,1);
}
void BootloaderProtocolSendNACK(unsigned char Cmd)
{
*BootloaderProtocolGetDataBufferPtr() = 0;
BootloaderProtocolSendFrame(Cmd,1);
}
void BootloaderProtocolSendInitUploadResponse(char result)
{
int MaxSize = MAX_BOOTLOADER_PAYLOAD_SIZE;
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
*DataPtr++ = result;
if(result == 1)
{
char nibble = (char)((MaxSize >> 24) &0x000000FF);
*DataPtr++ = nibble;
nibble = (char)((MaxSize >> 16) &0x000000FF);
*DataPtr++ = nibble;
nibble = (char)((MaxSize >> 8) &0x000000FF);
*DataPtr++ = nibble;
nibble = (char)(MaxSize &0x000000FF);
*DataPtr++ = nibble;
}
else
{
*DataPtr++ = 0;
*DataPtr++ = 0;
*DataPtr++ = 0;
*DataPtr++ = 0;
}
BootloaderProtocolSendFrame(BOOTLOADER_INIT_UPLOAD_RESPONSE,5);
}
void BootloaderProtocolSendDataChunkResult(char ErrorCode, int ChunkValue)
{
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
*DataPtr++ = ErrorCode;
char nibble = (char)((ChunkValue >> 24) &0x000000FF);
*DataPtr++ = nibble;
nibble = (char)((ChunkValue >> 16) &0x000000FF);
*DataPtr++ = nibble;
nibble = (char)((ChunkValue >> 8) &0x000000FF);
*DataPtr++ = nibble;
nibble = (char)(ChunkValue &0x000000FF);
*DataPtr++ = nibble;
BootloaderProtocolSendFrame(BOOTLOADER_SEND_DATA_CHUNK_RESPONSE,5);
}
void BootloaderProtocolSendBootloaderState(char State)
{
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
*DataPtr++ = State;
BootloaderProtocolSendFrame(BOOTLOADER_GET_STATE_RESPONSE,1);
}
void BootloaderProtocolSendFirmwareUploadResult(char Result)
{
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
*DataPtr++ = Result;
BootloaderProtocolSendFrame(BOOTLOADER_UPLOAD_FINISHED_RESPONSE,1);
}
void BootloaderProtocolSendFlashCheckResult(char Result)
{
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
*DataPtr++ = Result;
BootloaderProtocolSendFrame(BOOTLOADER_CHECK_FLASH_FIRMW_INTEGRITY_RESPONSE,1);
}
void BootloaderProtocolSendStoredFirmwareInfoResponse(unsigned char* FirmwareData, int size)
{
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
int i = 0;
for(i = 0; i < size; i++)
{
*DataPtr++ = *FirmwareData++;
}
BootloaderProtocolSendFrame(BOOTLOADER_GET_STORED_FIRMWARE_INFO_RESPONSE,size);
}
+123
View File
@@ -0,0 +1,123 @@
/**********************************************************************
Project: Automatic cat feeder
Date: march 19 2006
Author: Jean-Fran�ois Martel
Target: PIC 18F252
Compiler: Microchip mcc18
Filename: Protocol.h
File description: Communication protocol implementation.
jean-francois.martel@polymtl.ca
**********************************************************************/
#ifndef BOOTLOADERPROTOCOL_H
#define BOOTLOADERPROTOCOL_H
//Protocol buffer specific definitions
#define MAX_BOOTLOADER_PAYLOAD_SIZE 150
#define BOOTLOADER_FRAME_HEADER 0xDEADBEEF
#define BOOTLOADER_FRAME_HEADER_1 0xDE
#define BOOTLOADER_FRAME_HEADER_2 0xAD
#define BOOTLOADER_FRAME_HEADER_3 0xBE
#define BOOTLOADER_FRAME_HEADER_4 0xEF
#define PROTOCOL_INFO_DATA_SIZE 13 //Header + Cmd + Size + CRC = 13 bytes
//State Machine states
enum States
{
Initialization,
RxHeader1,
RxHeader2,
RxHeader3,
RxHeader4,
RxCmd,
RxPayloadSize1,
RxPayloadSize2,
RxPayloadSize3,
RxPayloadSize4,
RxPayload,
RxCRC1,
RxCRC2,
RxCRC3,
RxCRC4
};
enum eBootloaderProtocolDataTransferError
{
BOOTLOADER_CHUNK_TRANSFER_SUCCESS = 1,
BOOTLOADER_CHUNK_TRANSFER_ERROR_RESEND = 2,
BOOTLOADER_CHUNK_TRANSFER_ERROR_FLASH_FAILURE = 3,
BOOTLOADER_CHUNK_TRANSFER_ERROR_INVALID_CHUNK_INDEX = 4,
BOOTLOADER_CHUNK_TRANSFER_ERROR_FLASH_ERROR = 5,
BOOTLOADER_CHUNK_TRANSFER_MAX_ERROR
};
enum eBootloaderProtocolInitTransferError
{
BOOTLOADEDR_INIT_TRANSFER_ERROR = 0,
BOOTLOADEDR_INIT_TRANSFER_OK = 1,
BOOTLOADEDR_INIT_TRANSFER_ERROR_FLASH_NOT_ERASED,
BOOTLOADEDR_INIT_TRANSFER_MAX_ERROR
};
enum eBootloaderUploadResult
{
BOOTLOADER_UPLOAD_FAILED_UNKNOWN_ERROR = 0,
BOOTLOADER_UPLOAD_SUCCESS = 1,
BOOTLOADER_UPLOAD_FAILED_FLASH_VERIFICATION_ERROR = 2,
BOOTLOADER_UPLOAD_MAX_ERROR
};
enum eFlashCheckResult
{
FLASH_CHECK_FAILED = 0,
FLASH_CHECK_SUCCESS = 1,
FLASH_CHECK_MAX_RESULT
};
//enum DEVICES_IDS
//{
// ID_MASTER, //Master Controller
// ID_CONSOLE, //LCD Console
// ID_PC, //PC
// ID_AV_MUX, //Audio Video Multiplexer
// ID_IR_REMOTE,
// ID_DEADBOLT
//};
//enum MESSAGE_IDS
//{
// TX_NETWORK_ACK = 1,
// RX_GET_STATUS,
// TX_DEADBOLT_STATUS,
//
// MAX_NETWORK_CMD
//};
//State machine states definition
void BootloaderProtocolInit(void);
void BootloaderProtocolStateMachine(unsigned char STATE);
void BootloaderProtocolResetStateMachine(void);
void BootloaderProtocolProtocolAnalyzeNewData(unsigned char *DataBuf, int size);
void BootloaderProtocolSendFrame(unsigned char Cmd, int size);
unsigned char *BootloaderProtocolGetDataBufferPtr();
void BootloaderProtocolSendHeartbeat();
void BootloaderProtocolSendACK(unsigned char Cmd);
void BootloaderProtocolSendNACK(unsigned char Cmd);
void BootloaderProtocolSendInitUploadResponse(char result);
void BootloaderProtocolSendDataChunkResult(char ErrorCode, int ChunkValue);
void BootloaderProtocolSendBootloaderState(char State);
void BootloaderProtocolSendFirmwareUploadResult(char Result);
void BootloaderProtocolSendFlashCheckResult(char Result);
void BootloaderProtocolSendStoredFirmwareInfoResponse(unsigned char* FirmwareData, int size);
#endif
+79
View File
@@ -0,0 +1,79 @@
//#include <proc/p32mx440f256h.h>
#include "ChaletPowerRelay.h"
#include "BoardCfg.h"
#include "timer.h"
#define PIN_ACTIVE 1
#define PIN_INACTIVE 0
bool PowerRelayState;
void InitChaletPowerRelay()
{
POWER_RELAY_ON_PIN = PIN_INACTIVE;
POWER_RELAY_OFF_PIN = PIN_INACTIVE;
PowerRelayState = CHALET_POWER_RELAY_UNKNOWN_STATE;
TimerStop(CHALET_POWER_RELAY_COIL_TIMER);
}
void ChaletPowerRelayTick()
{
if(CHALET_12V_PRESENCE_PIN == CHALET_12V_POWER_STATE_ON)
{
if(PowerRelayState == CHALET_POWER_RELAY_OFF_STATE)
{
printf("Inverter turned ON\n");
}
PowerRelayState = CHALET_POWER_RELAY_ON_STATE;
}
else
{
if(PowerRelayState == CHALET_POWER_RELAY_ON_STATE)
{
printf("Inverter turned OFF\n");
}
PowerRelayState = CHALET_POWER_RELAY_OFF_STATE;
}
if(IsTimerRunning(CHALET_POWER_RELAY_COIL_TIMER) == true)
{
if(IsTimerExpired(CHALET_POWER_RELAY_COIL_TIMER))
{
POWER_RELAY_ON_PIN = PIN_INACTIVE;
POWER_RELAY_OFF_PIN = PIN_INACTIVE;
TimerStop(CHALET_POWER_RELAY_COIL_TIMER);
}
}
if(IsTimerExpired(CHALET_POWER_RELAY_AUTOTURNOFF_TIMER))
{
ChaletPowerRelayTurnOff();
}
}
void ChaletPowerRelayKickTimer()
{
TimerStartSeconds(CHALET_POWER_RELAY_AUTOTURNOFF_TIMER,CHALET_OFFLINE_POWER_RELAY_RESET_TIMEOUT);
}
bool ChaletPowerRelayTurnOn()
{
POWER_RELAY_ON_PIN = PIN_ACTIVE;
TimerStart(CHALET_POWER_RELAY_COIL_TIMER,CHALET_POWER_RELAY_COIL_TIMEOUT);
// PowerRelayState = CHALET_POWER_RELAY_ON_STATE;
return true;
}
bool ChaletPowerRelayTurnOff()
{
POWER_RELAY_OFF_PIN = PIN_ACTIVE;
TimerStart(CHALET_POWER_RELAY_COIL_TIMER,CHALET_POWER_RELAY_COIL_TIMEOUT);
// PowerRelayState = CHALET_POWER_RELAY_OFF_STATE;
return true;
}
char GetChaletPowerRelayState()
{
return (char)PowerRelayState;
}
+37
View File
@@ -0,0 +1,37 @@
/*
* File: ChaletPowerRelay.h
* Author: JF
*
* Created on November 30, 2018, 7:33 PM
*/
#ifndef CHALETPOWERRELAY_H
#define CHALETPOWERRELAY_H
#include "define.h"
#define CHALET_OFFLINE_POWER_RELAY_RESET_TIMEOUT 43200 //43,200 = 12 hours in seconds
enum eChaletPowerRelayState
{
CHALET_POWER_RELAY_OFF_STATE = 0,
CHALET_POWER_RELAY_ON_STATE,
CHALET_POWER_RELAY_UNKNOWN_STATE
};
#define CHALET_12V_POWER_STATE_ON 0
#define CHALET_12V_POWER_STATE_OFF 1
#define CHALET_POWER_RELAY_COIL_TIMEOUT 200 //ms
void InitChaletPowerRelay();
void ChaletPowerRelayTick();
bool ChaletPowerRelayTurnOn();
bool ChaletPowerRelayTurnOff();
char GetChaletPowerRelayState();
void ChaletPowerRelayKickTimer();
#endif /* CHALETPOWERRELAY_H */
+130
View File
@@ -0,0 +1,130 @@
#include "BoardCfg.h"
int InitBoard()
{
HEARTBEAT_LED_1_PIN_DIR = PIN_OUTPUT;
HEARTBEAT_LED_2_PIN_DIR = PIN_OUTPUT;
HEARTBEAT_LED_2_PIN = LED_OFF;
HEARTBEAT_LED_1_PIN = LED_ON;
LORA_ACTIVITY_LED_PIN_DIR = PIN_OUTPUT;
LORA_ACTIVITY_LED_PIN = LED_OFF;
// GP_DEBUG_1_PIN_DIR = PIN_OUTPUT;
// GP_DEBUG_1_PIN = 0;
// GP_DEBUG_2_PIN_DIR = PIN_OUTPUT;
// GP_DEBUG_2_PIN = 0;
SPI_SDI_PIN_DIR = PIN_INPUT;
SD_SPI_SS_PIN_DIR = PIN_OUTPUT;
SPI_SDO_PIN_DIR = PIN_OUTPUT;
SPI_SCK_PIN_DIR = PIN_OUTPUT;
FLASH_SS_PIN_DIR = PIN_OUTPUT;
FLASH_SS_PIN = 1;
//Wifi (WINC1500 module)
WIFI_SPI_SS_PIN_DIR = PIN_OUTPUT;
WIFI_SPI_SS_PIN = 1;
WIFI_IRQ_PIN_DIR = PIN_INPUT;
// WIFI_SPI_CFG_PIN_DIR = PIN_OUTPUT;
// WIFI_SPI_CFG_PIN = 0;
WIFI_CHP_EN_PIN_DIR = PIN_OUTPUT;
WIFI_CHP_EN_PIN = 0;
WIFI_CHP_RST_PIN_DIR = PIN_OUTPUT;
WIFI_CHP_RST_PIN = 0;
// DOOR_PAD_D0_PIN_DIR = PIN_INPUT;
// DOOR_PAD_D1_PIN_DIR
// DOOR_PAD_D1_PIN
//Wifi chip IRQ
IEC0bits.INT0IE = 0;
IFS0bits.INT0IF = 0;
INTCONbits.INT0EP = 0; //Falling edge
IPC0bits.INT0IP = 3;
IPC0bits.INT0IS = 0;
IEC0bits.INT0IE = 1;
//Wifi chip SPI
SPI2CON = 0;
SPI2CONbits.MSTEN = 1;
SPI2CONbits.CKE = 1;
SPI2CONbits.SMP = 0;
SPI2CONbits.CKP = 0;
SPI2BRG = SPICalculateBRG(PERIPHERAL_FREQ, 1000000);
// SPI2BRG = SPICalculateBRG(PERIPHERAL_FREQ, 50000);
SPI2CONbits.ON = 1;
//Chalet inverter power relay
POWER_RELAY_ON_PIN_DIR = PIN_OUTPUT;
POWER_RELAY_OFF_PIN_DIR = PIN_OUTPUT;
POWER_RELAY_ON_PIN = 0;
POWER_RELAY_OFF_PIN = 0;
//Harakiri relay
HARAKIRI_RELAY_ON_PIN_DIR = PIN_OUTPUT;
HARAKIRI_RELAY_ON_PIN= 0;
//12V presence detection input
CHALET_12V_PRESENCE_PIN_DIR = PIN_INPUT;
//Battery voltage measurement (analog input)
BATTERY_VOLTAGE_ANALOG_PIN_DIR = PIN_INPUT;
IEC0bits.INT1IE = 0;
IFS0bits.INT1IF = 0;
INTCONbits.INT1EP = 1; //Rising edge
IPC1bits.INT1IP = 2;
IPC1bits.INT1IS = 1;
// IEC0bits.INT1IE = 1;
// OC3CON = 0;
// OC3R = 0;
// OC3RS = 2000; //50% PWM
// OC3CONbits.OCTSEL = 0;
// OC3CONbits.OCM = 0b110; //PWM mode, no fault protection
//#ifdef __32MX330F064H__
// RPD2Rbits.RPD2R = 0b1011; //RD2 peripheral selection = OC3
//#endif
//
// T2CONbits.TON = 0; // Disable Timer
// // T2CONbits.TCS = 0; // Select internal instruction cycle clock
// T2CONbits.TGATE = 0; // Disable Gated Timer mode
// T2CONbits.TCKPS = 0b011; // Select 1:1 Prescaler
// TMR2 = 0x00; // Clear timer register
//
//
// IPC2bits.T2IP = 0x01; // Set Timer 2 Interrupt Priority Level
// IFS0bits.T2IF = 0; // Clear Timer 2 Interrupt Flag
// IEC0bits.T2IE = 0; // Disable Timer 2 interrupt
// T2CONbits.TON = 1; // Start Timer
//
// OC3CONbits.ON = 1;
//ADC test
AD1PCFG = 0xFFFF; //Sart with I/O pins configured as digital I/O
AD1PCFGbits.PCFG1 = 0;
TRISBbits.TRISB1 = PIN_INPUT;
AD1CON1 = 0;
AD1CON2 = 0;
AD1CON3 = 0;
AD1CHS = 0;
AD1CHSbits.CH0SA = 1; //AN1
AD1CON3bits.ADCS = 0xF0;
AD1CON3bits.SAMC = 0x01;
AD1CON1bits.ON = 1;
AD1CON1bits.SAMP = 1;
return RET_OK;
}
+204
View File
@@ -0,0 +1,204 @@
#include "BoardCfg.h"
int InitBoard()
{
HEARTBEAT_LED_1_PIN_DIR = PIN_OUTPUT;
HEARTBEAT_LED_2_PIN_DIR = PIN_OUTPUT;
HEARTBEAT_LED_2_PIN = LED_OFF;
HEARTBEAT_LED_1_PIN = LED_ON;
// LORA_ACTIVITY_LED_PIN_DIR = PIN_OUTPUT;
// LORA_ACTIVITY_LED_PIN = LED_OFF;
// GP_DEBUG_1_PIN_DIR = PIN_OUTPUT;
// GP_DEBUG_1_PIN = 0;
// GP_DEBUG_2_PIN_DIR = PIN_OUTPUT;
// GP_DEBUG_2_PIN = 0;
SPI_SDI_PIN_DIR = PIN_INPUT;
SD_SPI_SS_PIN_DIR = PIN_OUTPUT;
SPI_SDO_PIN_DIR = PIN_OUTPUT;
SPI_SCK_PIN_DIR = PIN_OUTPUT;
//////////////// SPI FLASH //////////////////
FLASH_SS_PIN_DIR = PIN_OUTPUT;
FLASH_SS_PIN = 1;
/////////////////////////// WIFI ///////////////////
//Wifi (WINC1500 module)
WIFI_SPI_SS_PIN_DIR = PIN_OUTPUT;
WIFI_SPI_SS_PIN = 1;
WIFI_IRQ_PIN_DIR = PIN_INPUT;
// WIFI_SPI_CFG_PIN_DIR = PIN_OUTPUT;
// WIFI_SPI_CFG_PIN = 0;
WIFI_CHP_EN_PIN_DIR = PIN_OUTPUT;
WIFI_CHP_EN_PIN = 0;
WIFI_CHP_RST_PIN_DIR = PIN_OUTPUT;
WIFI_CHP_RST_PIN = 0;
//Wifi chip IRQ
IEC0bits.INT0IE = 0;
IFS0bits.INT0IF = 0;
INTCONbits.INT0EP = 0; //Falling edge
IPC0bits.INT0IP = 3;
IPC0bits.INT0IS = 0;
IEC0bits.INT0IE = 1;
//Wifi chip SPI
SPI2CON = 0;
SPI2CONbits.MSTEN = 1;
SPI2CONbits.CKE = 1;
SPI2CONbits.SMP = 0;
SPI2CONbits.CKP = 0;
SPI2BRG = SPICalculateBRG(PERIPHERAL_FREQ, 1000000);
// SPI2BRG = SPICalculateBRG(PERIPHERAL_FREQ, 50000);
SPI2CONbits.ON = 1;
//////////////// INVERTER RELAY //////////////////
//Chalet inverter power relay
POWER_RELAY_ON_PIN_DIR = PIN_OUTPUT;
POWER_RELAY_OFF_PIN_DIR = PIN_OUTPUT;
POWER_RELAY_ON_PIN = 0;
POWER_RELAY_OFF_PIN = 0;
//////////////// HARAKIRI RELAY //////////////////
//Harakiri relay
HARAKIRI_RELAY_ON_PIN_DIR = PIN_OUTPUT;
HARAKIRI_RELAY_ON_PIN= 0;
//12V presence detection input
CHALET_12V_PRESENCE_PIN_DIR = PIN_INPUT;
//////////////// BATTERY MONITOR //////////////////
//Battery voltage measurement (analog input)
BATTERY_VOLTAGE_ANALOG_PIN_DIR = PIN_INPUT;
//ADC Config
AD1PCFG = 0xFFFF; //Sart with I/O pins configured as digital I/O
AD1PCFGbits.PCFG1 = 0;
AD1PCFGbits.PCFG2 = 0;
TRISBbits.TRISB1 = PIN_INPUT;
TRISBbits.TRISB2 = PIN_INPUT;
AD1CON1 = 0;
AD1CON2 = 0;
AD1CON3 = 0;
AD1CHS = 0;
AD1CHSbits.CH0SA = 1; //AN1
AD1CON3bits.ADCS = 0xF0;
AD1CON3bits.SAMC = 0x01;
AD1CON1bits.ON = 1;
AD1CON1bits.SAMP = 1;
//////////////// TEMPERATURE SENSOR //////////////////
//Onboard temperature sensor (SPI)
TEMP_SENSOR_CS_PIN_DIR = PIN_OUTPUT;
TEMP_SENSOR_CS_PIN = 1;
TEMP_SENSOR_SPI_SDO_PIN_DIR = PIN_OUTPUT;
TEMP_SENSOR_SPI_SDI_PIN_DIR = PIN_INPUT;
TEMP_SENSOR_SPI_SCK_PIN_DIR = PIN_OUTPUT;
SPI3CON = 0;
SPI3CONbits.MSTEN = 1;
SPI3CONbits.CKE = 1;
SPI3CONbits.SMP = 0;
SPI3CONbits.CKP = 0;
SPI3BRG = SPICalculateBRG(PERIPHERAL_FREQ, 1000000);
SPI3CONbits.ON = 1;
//////////////// CURRENT SENSOR //////////////////
//Analog (Hall effect) current sensor
CURRENT_SENSOR_IN1_PIN_DIR = PIN_INPUT; //AN2
CURRENT_SENSOR_IN2_PIN_DIR = PIN_INPUT; //AN0
//TODO
// AD1CHS = 0;
// AD1CHSbits.CH0SA = 1; //AN2
// AD1CON3bits.ADCS = 0xF0;
// AD1CON3bits.SAMC = 0x01;
// AD1CON1bits.ON = 1;
// AD1CON1bits.SAMP = 1;
//////////////// LORA //////////////////
LORA_MODULE_RELAY_PIN_DIR = PIN_OUTPUT;
LORA_MODULE_RELAY_PIN = 0;
// LORA_MODULE_M0_PIN_DIR = PIN_INPUT;
// LORA_MODULE_M0_PIN = 0;
// LORA_MODULE_M1_PIN_DIR = PIN_INPUT;
// LORA_MODULE_M1_PIN = 0;
LORA_MODULE_INT_PIN_DIR = PIN_INPUT;
LORA_MODULE_RX_LED_PIN_DIR = PIN_OUTPUT;
LORA_MODULE_RX_LED_PIN = LED_OFF;
LORA_MODULE_TX_LED_PIN_DIR = PIN_OUTPUT;
LORA_MODULE_TX_LED_PIN = LED_OFF;
//////////////// LCD SCREEN //////////////////
//LCD Screen
LCD_RS_PIN_DIR = PIN_OUTPUT;
LCD_RS_PIN = 0;
LCD_RW_PIN_DIR = PIN_OUTPUT;
LCD_RW_PIN = 0;
LCD_E_PIN_DIR = PIN_OUTPUT;
LCD_E_PIN = 0;
LCD_DB4_PIN_DIR = PIN_OUTPUT;
LCD_DB4_PIN = 0;
LCD_DB5_PIN_DIR = PIN_OUTPUT;
LCD_DB5_PIN = 0;
LCD_DB6_PIN_DIR = PIN_OUTPUT;
LCD_DB6_PIN = 0;
LCD_DB7_PIN_DIR = PIN_OUTPUT;
LCD_DB7_PIN = 0;
LCD_SCROLL_BTN_PIN_DIR = PIN_INPUT;
////// MISC UNUSED STUFF ///////////
// IEC0bits.INT1IE = 0;
// IFS0bits.INT1IF = 0;
// INTCONbits.INT1EP = 1; //Rising edge
// IPC1bits.INT1IP = 2;
// IPC1bits.INT1IS = 1;
// IEC0bits.INT1IE = 1;
// OC3CON = 0;
// OC3R = 0;
// OC3RS = 2000; //50% PWM
// OC3CONbits.OCTSEL = 0;
// OC3CONbits.OCM = 0b110; //PWM mode, no fault protection
//#ifdef __32MX330F064H__
// RPD2Rbits.RPD2R = 0b1011; //RD2 peripheral selection = OC3
//#endif
//
// T2CONbits.TON = 0; // Disable Timer
// // T2CONbits.TCS = 0; // Select internal instruction cycle clock
// T2CONbits.TGATE = 0; // Disable Gated Timer mode
// T2CONbits.TCKPS = 0b011; // Select 1:1 Prescaler
// TMR2 = 0x00; // Clear timer register
//
//
// IPC2bits.T2IP = 0x01; // Set Timer 2 Interrupt Priority Level
// IFS0bits.T2IF = 0; // Clear Timer 2 Interrupt Flag
// IEC0bits.T2IE = 0; // Disable Timer 2 interrupt
// T2CONbits.TON = 1; // Start Timer
//
// OC3CONbits.ON = 1;
return RET_OK;
}
+15
View File
@@ -0,0 +1,15 @@
#include "define.h"
#include "CurrentSensor.h"
#include "ina219.h"
int CurrentSensorInit()
{
ina219SetCalibration_16V_200mA();
return RET_OK;
}
int GetSolarPanelCurrent()
{
return ina219GetCurrent();
}
+16
View File
@@ -0,0 +1,16 @@
/*
* File: SPI.h
* Author: JF
*
* Created on December 2, 2018, 3:36 PM
*/
#ifndef CURRENTSENSOR_H
#define CURRENTSENSOR_H
int CurrentSensorInit();
int GetSolarPanelCurrent();
#endif /* CURRENTSENSOR_H */
+42
View File
@@ -0,0 +1,42 @@
/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C code file.
*/
/* ************************************************************************** */
/* ¤Revision:
000 20100616 JFM,
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
/* ************************************************************************** */
/* Includes */
#include "DigitalIO.h"
//#include "define.h"
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void InitDigitalIO(void)
{
}
//EOF
+36
View File
@@ -0,0 +1,36 @@
/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C header file.
*/
/* ************************************************************************** */
/* ¤Revision:
000 20100616 JFM,
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
#ifndef DIGITAL_IO_H
#define DIGITAL_IO_H
#include "BoardCfg.h"
#endif
//EOF
+225
View File
@@ -0,0 +1,225 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be */
/* attached to the FatFs via a glue function rather than modifying it. */
/* This is an example of glue functions to attach various exsisting */
/* storage control modules to the FatFs module with a defined API. */
/*-----------------------------------------------------------------------*/
#include "diskio.h" /* FatFs lower layer API */
/* Definitions of physical drive number for each drive */
#define DEV_RAM 1 /* Example: Map Ramdisk to physical drive 0 */
#define DEV_MMC 0 /* Example: Map MMC/SD card to physical drive 1 */
#define DEV_USB 2 /* Example: Map USB MSD to physical drive 2 */
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_RAM :
// result = RAM_disk_status();
// translate the reslut code here
return stat;
case DEV_MMC :
// result = MMC_disk_status();
// translate the reslut code here
return stat;
case DEV_USB :
// result = USB_disk_status();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_RAM :
//result = RAM_disk_initialize();
// translate the reslut code here
return stat;
case DEV_MMC :
// result = MMC_disk_initialize();
// translate the reslut code here
return stat;
case DEV_USB :
// result = USB_disk_initialize();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// translate the arguments here
// result = RAM_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case DEV_MMC :
// translate the arguments here
// result = MMC_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case DEV_USB :
// translate the arguments here
// result = USB_disk_read(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// translate the arguments here
// result = RAM_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case DEV_MMC :
// translate the arguments here
// result = MMC_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case DEV_USB :
// translate the arguments here
// result = USB_disk_write(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
// Process of the command for the RAM drive
return res;
case DEV_MMC :
// Process of the command for the MMC/SD card
return res;
case DEV_USB :
// Process of the command the USB drive
return res;
}
return RES_PARERR;
}
+101
View File
@@ -0,0 +1,101 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2014 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h"
#define _USE_WRITE 1
#define _USE_IOCTL 1
#define _USE
/* Status of Disk Functions */
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/*---------------------------------------*/
/* Prototypes for disk control functions */
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
void disk_timerproc(void);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
///* Generic command (Not used by FatFs) */
//#define CTRL_POWER 5 /* Get/Set power status */
//#define CTRL_LOCK 6 /* Lock/Unlock media removal */
//#define CTRL_EJECT 7 /* Eject media */
//#define CTRL_FORMAT 8 /* Create physical format on the media */
/* Generic command (Not used by FatFs) */
#define CTRL_FORMAT 5 /* Create physical format on the media */
#define CTRL_POWER_IDLE 6 /* Put the device idle state */
#define CTRL_POWER_OFF 7 /* Put the device off state */
#define CTRL_LOCK 8 /* Lock media removal */
#define CTRL_UNLOCK 9 /* Unlock media removal */
#define CTRL_EJECT 10 /* Eject media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* MMC card type flags (MMC_GET_TYPE) */
#define CT_MMC 0x01 /* MMC ver 3 */
#define CT_SD1 0x02 /* SD ver 1 */
#define CT_SD2 0x04 /* SD ver 2 */
#define CT_SDC (CT_SD1|CT_SD2) /* SD */
#define CT_BLOCK 0x08 /* Block addressing */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif
File diff suppressed because it is too large Load Diff
+366
View File
@@ -0,0 +1,366 @@
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem module R0.13a /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2017, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/
/----------------------------------------------------------------------------*/
#ifndef FF_DEFINED
#define FF_DEFINED 89352 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if FF_DEFINED != FFCONF_DEF
#error Wrong configuration file (ffconf.h).
#endif
/* Definitions of volume management */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#endif
/* Type of path name strings on FatFs API */
#ifndef _INC_TCHAR
#define _INC_TCHAR
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
typedef char TCHAR;
#define _T(x) u8 ## x
#define _TEXT(x) u8 ## x
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 2)
#error Wrong FF_LFN_UNICODE setting
#else /* ANSI/OEM code in SBCS/DBCS */
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* Type of file size variables */
#if FF_FS_EXFAT
typedef QWORD FSIZE_t;
#else
typedef DWORD FSIZE_t;
#endif
/* Filesystem object structure (FATFS) */
typedef struct {
BYTE fs_type; /* Filesystem type (0:N/A) */
BYTE pdrv; /* Physical drive number */
BYTE n_fats; /* Number of FATs (1 or 2) */
BYTE wflag; /* win[] flag (b0:dirty) */
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
WORD id; /* Volume mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
WORD csize; /* Cluster size [sectors] */
#if FF_MAX_SS != FF_MIN_SS
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
#endif
#if FF_USE_LFN
WCHAR* lfnbuf; /* LFN working buffer */
#endif
#if FF_FS_EXFAT
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */
#endif
#if FF_FS_REENTRANT
FF_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !FF_FS_READONLY
DWORD last_clst; /* Last allocated cluster */
DWORD free_clst; /* Number of free clusters */
#endif
#if FF_FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#if FF_FS_EXFAT
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
#endif
#endif
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
DWORD fsize; /* Size of an FAT [sectors] */
DWORD volbase; /* Volume base sector */
DWORD fatbase; /* FAT base sector */
DWORD dirbase; /* Root directory base sector/cluster */
DWORD database; /* Data base sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;
/* Object ID and allocation information (FFOBJID) */
typedef struct {
FATFS* fs; /* Pointer to the hosting volume of this object */
WORD id; /* Hosting volume mount ID */
BYTE attr; /* Object attribute */
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
#if FF_FS_EXFAT
DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */
DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */
#endif
#if FF_FS_LOCK
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
#endif
} FFOBJID;
/* File object structure (FIL) */
typedef struct {
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
#if !FF_FS_READONLY
DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */
#endif
#if FF_USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
#endif
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
FFOBJID obj; /* Object identifier */
DWORD dptr; /* Current read/write offset */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector (0:Read operation has terminated) */
BYTE* dir; /* Pointer to the directory item in the win[] */
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
#if FF_USE_LFN
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
#endif
#if FF_USE_FIND
const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} DIR;
/* File information structure (FILINFO) */
typedef struct {
FSIZE_t fsize; /* File size */
WORD fdate; /* Modified date */
WORD ftime; /* Modified time */
BYTE fattrib; /* File attribute */
#if FF_USE_LFN
TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
#else
TCHAR fname[12 + 1]; /* File name */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
FRESULT f_close (FIL* fp); /* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */
FRESULT f_truncate (FIL* fp); /* Truncate the file */
FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
FRESULT f_closedir (DIR* dp); /* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */
FRESULT f_setcp (WORD cp); /* Set current code page */
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->obj.objsize)
#define f_rewind(fp) f_lseek((fp), 0)
#define f_rewinddir(dp) f_readdir((dp), 0)
#define f_rmdir(path) f_unlink(path)
#define f_unmount(path) f_mount(0, path, 0)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !FF_FS_READONLY && !FF_FS_NORTC
DWORD get_fattime (void);
#endif
/* LFN support functions */
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */
DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
#endif
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
void* ff_memalloc (UINT msize); /* Allocate memory block */
void ff_memfree (void* mblock); /* Free memory block */
#endif
/* Sync functions */
#if FF_FS_REENTRANT
int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */
int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */
void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */
int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access mode and open method flags (3rd argument of f_open) */
#define FA_READ 0x01
#define FA_WRITE 0x02
#define FA_OPEN_EXISTING 0x00
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA_OPEN_APPEND 0x30
/* Fast seek controls (2nd argument of f_lseek) */
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
/* Format options (2nd argument of f_mkfs) */
#define FM_FAT 0x01
#define FM_FAT32 0x02
#define FM_EXFAT 0x04
#define FM_ANY 0x07
#define FM_SFD 0x08
/* Filesystem type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
#define FS_EXFAT 4
/* File attribute bits for directory entry (FILINFO.fattrib) */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#ifdef __cplusplus
}
#endif
#endif /* FF_DEFINED */
+283
View File
@@ -0,0 +1,283 @@
/*---------------------------------------------------------------------------/
/ FatFs - Configuration file
/---------------------------------------------------------------------------*/
#define FFCONF_DEF 89352 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_READONLY 0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define FF_FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
/ 0: Basic functions are fully enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define FF_USE_STRFUNC 0
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define FF_USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define FF_USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define FF_USE_FASTSEEK 0
/* This option switches fast seek function. (0:Disable or 1:Enable) */
#define FF_USE_EXPAND 0
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#define FF_USE_CHMOD 0
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
#define FF_USE_LABEL 0
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define FF_USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#define FF_CODE_PAGE 437
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect code page setting can cause a file open failure.
/
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 771 - KBL
/ 775 - Baltic
/ 850 - Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 860 - Portuguese
/ 861 - Icelandic
/ 862 - Hebrew
/ 863 - Canadian French
/ 864 - Arabic
/ 865 - Nordic
/ 866 - Russian
/ 869 - Greek 2
/ 932 - Japanese (DBCS)
/ 936 - Simplified Chinese (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese (DBCS)
/ 0 - Include all code pages above and configured by f_setcp()
*/
#define FF_USE_LFN 0
#define FF_MAX_LFN 255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
/ 0: Disable LFN. FF_MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
/ be in range of 12 to 255. It is recommended to be set 255 to fully support LFN
/ specification.
/ When use stack for the working buffer, take care on stack overflow. When use heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree() in ffsystem.c, need to be added to the project. */
#define FF_LFN_UNICODE 0
/* This option switches the character encoding on the API when LFN is enabled.
/
/ 0: ANSI/OEM in current CP (TCHAR = char)
/ 1: Unicode in UTF-16 (TCHAR = WCHAR)
/ 2: Unicode in UTF-8 (TCHAR = char)
/
/ Also behavior of string I/O functions will be affected by this option.
/ When LFN is not enabled, this option has no effect. */
#define FF_LFN_BUF 255
#define FF_SFN_BUF 12
/* This set of options defines size of file name members in the FILINFO structure
/ which is used to read out directory items. These values should be suffcient for
/ the file names to read. The maximum possible length of the read file name depends
/ on character encoding. When LFN is not enabled, these options have no effect. */
#define FF_STRF_ENCODE 3
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
/ This option selects assumption of character encoding ON THE FILE to be
/ read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
#define FF_FS_RPATH 0
/* This option configures support for relative path.
/
/ 0: Disable relative path and remove related functions.
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
/ 2: f_getcwd() function is available in addition to 1.
*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define FF_VOLUMES 1
/* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 0
#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
/* FF_STR_VOLUME_ID switches string support for volume ID.
/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each
/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for
/ the drive ID strings are: A-Z and 0-9. */
#define FF_MULTI_PARTITION 0
/* This option switches support for multiple volumes on the physical drive.
/ By default (0), each logical drive number is bound to the same physical drive
/ number and only an FAT volume found on the physical drive will be mounted.
/ When this function is enabled (1), each logical drive number can be bound to
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/ funciton will be available. */
#define FF_MIN_SS 512
#define FF_MAX_SS 512
/* This set of options configures the range of sector size to be supported. (512,
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
/ for variable sector size mode and disk_ioctl() function needs to implement
/ GET_SECTOR_SIZE command. */
#define FF_USE_TRIM 0
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
/ disk_ioctl() function. */
#define FF_FS_NOFSINFO 0
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
/ option, and f_getfree() function at first time after volume mount will force
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
/
/ bit0=0: Use free cluster count in the FSINFO if available.
/ bit0=1: Do not trust free cluster count in the FSINFO.
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
*/
/*---------------------------------------------------------------------------/
/ System Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_TINY 0
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
#define FF_FS_EXFAT 0
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ When enable exFAT, also LFN needs to be enabled.
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
#define FF_FS_NORTC 1
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2017
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */
#define FF_FS_LOCK 0
/* The option FF_FS_LOCK switches file lock function to control duplicated file open
/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
/ is 1.
/
/ 0: Disable file lock function. To avoid volume corruption, application program
/ should avoid illegal open, remove and rename to the open objects.
/ >0: Enable file lock function. The value defines how many files/sub-directories
/ can be opened simultaneously under file lock control. Note that the file
/ lock control is independent of re-entrancy. */
#define FF_FS_REENTRANT 0
#define FF_FS_TIMEOUT 1000
#define FF_SYNC_t HANDLE
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
/ module itself. Note that regardless of this option, file access to different
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
/ to the same volume is under control of this function.
/
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
/ function, must be added to the project. Samples are available in
/ option/syscall.c.
/
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.h. */
/* #include <windows.h> // O/S definitions */
/*--- End of configuration options ---*/
+171
View File
@@ -0,0 +1,171 @@
/*------------------------------------------------------------------------*/
/* Sample Code of OS Dependent Functions for FatFs */
/* (C)ChaN, 2017 */
/*------------------------------------------------------------------------*/
#include "ff.h"
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
/*------------------------------------------------------------------------*/
/* Allocate a memory block */
/*------------------------------------------------------------------------*/
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */
UINT msize /* Number of bytes to allocate */
)
{
return malloc(msize); /* Allocate a new memory block with POSIX API */
}
/*------------------------------------------------------------------------*/
/* Free a memory block */
/*------------------------------------------------------------------------*/
void ff_memfree (
void* mblock /* Pointer to the memory block to free (nothing to do for null) */
)
{
free(mblock); /* Free the memory block with POSIX API */
}
#endif
#if FF_FS_REENTRANT /* Mutal exclusion */
/*------------------------------------------------------------------------*/
/* Create a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to create a new
/ synchronization object for the volume, such as semaphore and mutex.
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
*/
//const osMutexDef_t Mutex[FF_VOLUMES]; /* CMSIS-RTOS */
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
BYTE vol, /* Corresponding volume (logical drive number) */
FF_SYNC_t *sobj /* Pointer to return the created sync object */
)
{
/* Win32 */
*sobj = CreateMutex(NULL, FALSE, NULL);
return (int)(*sobj != INVALID_HANDLE_VALUE);
/* uITRON */
// T_CSEM csem = {TA_TPRI,1,1};
// *sobj = acre_sem(&csem);
// return (int)(*sobj > 0);
/* uC/OS-II */
// OS_ERR err;
// *sobj = OSMutexCreate(0, &err);
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// *sobj = xSemaphoreCreateMutex();
// return (int)(*sobj != NULL);
/* CMSIS-RTOS */
// *sobj = osMutexCreate(Mutex + vol);
// return (int)(*sobj != NULL);
}
/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
/ the f_mount() function fails with FR_INT_ERR.
*/
int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */
FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
)
{
/* Win32 */
return (int)CloseHandle(sobj);
/* uITRON */
// return (int)(del_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err);
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// vSemaphoreDelete(sobj);
// return 1;
/* CMSIS-RTOS */
// return (int)(osMutexDelete(sobj) == osOK);
}
/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
*/
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
FF_SYNC_t sobj /* Sync object to wait */
)
{
/* Win32 */
return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0);
/* uITRON */
// return (int)(wai_sem(sobj) == E_OK);
/* uC/OS-II */
// OS_ERR err;
// OSMutexPend(sobj, FF_FS_TIMEOUT, &err));
// return (int)(err == OS_NO_ERR);
/* FreeRTOS */
// return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
/* CMSIS-RTOS */
// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
}
/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/
void ff_rel_grant (
FF_SYNC_t sobj /* Sync object to be signaled */
)
{
/* Win32 */
ReleaseMutex(sobj);
/* uITRON */
// sig_sem(sobj);
/* uC/OS-II */
// OSMutexPost(sobj);
/* FreeRTOS */
// xSemaphoreGive(sobj);
/* CMSIS-RTOS */
// osMutexRelease(sobj);
}
#endif
File diff suppressed because it is too large Load Diff
+38
View File
@@ -0,0 +1,38 @@
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
#ifndef FF_INTEGER
#define FF_INTEGER
#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
typedef unsigned __int64 QWORD;
#else /* Embedded platform */
/* These types MUST be 16-bit or 32-bit */
typedef int INT;
typedef unsigned int UINT;
/* This type MUST be 8-bit */
typedef unsigned char BYTE;
/* These types MUST be 16-bit */
typedef short SHORT;
typedef unsigned short WORD;
typedef unsigned short WCHAR;
/* These types MUST be 32-bit */
typedef long LONG;
typedef unsigned long DWORD;
/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
typedef unsigned long long QWORD;
#endif
#endif
+660
View File
@@ -0,0 +1,660 @@
/*------------------------------------------------------------------------/
/ MMCv3/SDv1/SDv2+ (in SPI mode) control module
/-------------------------------------------------------------------------/
/
/ Copyright (C) 2014, ChaN, all right reserved.
/
/ * This software is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/-------------------------------------------------------------------------*/
//#include <p24FJ64GA002.h>
//#include <plib.h>
#include "DigitalIO.h"
#include "diskio.h"
static inline __attribute__((always_inline)) unsigned char SPICalculateBRG(unsigned int pb_clk, unsigned int spi_clk);
static void set_fast_clk(void);
static void set_slow_clk(void);
/* Socket controls (Platform dependent) */
#define CS_LOW() SD_SPI_CS_PIN = 0 /* MMC CS = L */
#define CS_HIGH() SD_SPI_CS_PIN = 1 /* MMC CS = H */
#define MMC_CD (true) /* Card detected (yes:true, no:false, default:true) */
#define MMC_WP (false) /* Write protected (yes:true, no:false, default:false) */
/* SPI bit rate controls */
#define FCLK_SLOW() set_slow_clk() /* Set slow clock for card initialization (100k-400k) */
#define FCLK_FAST() set_fast_clk() /* Set fast clock for generic read/write */
/*--------------------------------------------------------------------------
Module Private Functions
---------------------------------------------------------------------------*/
/* Definitions for MMC/SDC command */
#define CMD0 (0) /* GO_IDLE_STATE */
#define CMD1 (1) /* SEND_OP_COND */
#define ACMD41 (41|0x80) /* SEND_OP_COND (SDC) */
#define CMD8 (8) /* SEND_IF_COND */
#define CMD9 (9) /* SEND_CSD */
#define CMD10 (10) /* SEND_CID */
#define CMD12 (12) /* STOP_TRANSMISSION */
#define ACMD13 (13|0x80) /* SD_STATUS (SDC) */
#define CMD16 (16) /* SET_BLOCKLEN */
#define CMD17 (17) /* READ_SINGLE_BLOCK */
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
#define CMD23 (23) /* SET_BLOCK_COUNT */
#define ACMD23 (23|0x80) /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24 (24) /* WRITE_BLOCK */
#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
#define CMD41 (41) /* SEND_OP_COND (ACMD) */
#define CMD55 (55) /* APP_CMD */
#define CMD58 (58) /* READ_OCR */
static volatile
DSTATUS Stat = STA_NOINIT; /* Disk status */
static volatile
UINT Timer1, Timer2; /* 1000Hz decrement timer */
static
UINT CardType;
static inline __attribute__((always_inline)) unsigned char SPICalculateBRG(unsigned int pb_clk, unsigned int spi_clk)
{
unsigned int brg;
brg = pb_clk / (2 * spi_clk);
if(pb_clk % (2 * spi_clk))
brg++;
if(brg > 0x100)
brg = 0x100;
if(brg)
brg--;
return (unsigned char) brg;
}
/*-----------------------------------------------------------------------*/
/* Interface Controls (Platform dependent) */
/*-----------------------------------------------------------------------*/
/* When the target system does not support socket power control, there */
/* is nothing to do in these functions. */
static void power_on (void)
{
SPI2CON = 0;
SPI2CONbits.MSTEN = 1;
SPI2CONbits.CKE = 0;
SPI2CONbits.CKP = 1;
FCLK_SLOW();
SPI2CONbits.ON = 1;
return;
}
static void power_off (void)
{
SPI2CONbits.ON = 0; /* Disable SPI2 */
}
static void set_slow_clk(void)
{
unsigned WasON = SPI2CONbits.ON;
SPI2CONbits.ON = 0;
SPI2BRG = SPICalculateBRG(80000000,40000);
SPI2CONbits.ON = WasON;
}
static void set_fast_clk(void)
{
unsigned WasON = SPI2CONbits.ON;
SPI2CONbits.ON = 0;
SPI2BRG = SPICalculateBRG(80000000,20000000);
SPI2CONbits.ON = WasON;
}
/*-----------------------------------------------------------------------*/
/* SPI Transactions (Platform dependent) */
/*-----------------------------------------------------------------------*/
/* Single byte SPI transaction */
static BYTE xchg_spi (BYTE dat)
{
#ifndef USE_PINGUINO
while( SPI2STATbits.SPITBF == 1 )
{
}
#endif
// ----------------
// sending data
// ----------------
SPI2BUF = dat;
while(SPI2STATbits.SPIRBF == 0)
{
}
return (BYTE)SPI2BUF; /* Get received byte */
}
/* Multi-byte SPI transaction (transmit) */
static
void xmit_spi_multi (
const BYTE* buff, /* Data to be sent */
UINT cnt /* Number of bytes to send */
)
{
do {
SPI2BUF = *buff++; /* Initiate an SPI transaction */
while (SPI2STATbits.SPIRBF == 0) ; /* Wait for end of the SPI transaction */
SPI2BUF; /* Discard received byte */
SPI2BUF = *buff++;
while (SPI2STATbits.SPIRBF == 0) ;
SPI2BUF;
} while (cnt -= 2);
}
/* Multi-byte SPI transaction (receive) */
static
void rcvr_spi_multi (
BYTE* buff, /* Buffer to store received data */
UINT cnt /* Number of bytes to receive */
)
{
do {
SPI2BUF = 0xFF; /* Initiate an SPI transaction */
while (SPI2STATbits.SPIRBF == 0) ; /* Wait for end of the SPI transaction */
*buff++ = SPI2BUF; /* Get received byte */
SPI2BUF = 0xFF;
while (SPI2STATbits.SPIRBF == 0) ;
*buff++ = SPI2BUF;
} while (cnt -= 2);
}
/*-----------------------------------------------------------------------*/
/* Wait for card ready */
/*-----------------------------------------------------------------------*/
static
int wait_ready (void)
{
BYTE d;
Timer2 = 500; /* Wait for ready in timeout of 500ms */
do {
d = xchg_spi(0xFF);
} while ((d != 0xFF) && Timer2);
return (d == 0xFF) ? 1 : 0;
}
/*-----------------------------------------------------------------------*/
/* Deselect the card and release SPI bus */
/*-----------------------------------------------------------------------*/
static
void deselect (void)
{
CS_HIGH(); /* Set CS# high */
xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */
}
/*-----------------------------------------------------------------------*/
/* Select the card and wait ready */
/*-----------------------------------------------------------------------*/
static
int select (void) /* 1:Successful, 0:Timeout */
{
CS_LOW(); /* Set CS# low */
xchg_spi(0xFF); /* Dummy clock (force DO enabled) */
if (wait_ready()) return 1; /* Wait for card ready */
deselect();
return 0; /* Timeout */
}
/*-----------------------------------------------------------------------*/
/* Receive a data packet from MMC */
/*-----------------------------------------------------------------------*/
static
int rcvr_datablock ( /* 1:OK, 0:Failed */
BYTE *buff, /* Data buffer to store received data */
UINT btr /* Byte count (must be multiple of 4) */
)
{
BYTE token;
Timer1 = 100;
do { /* Wait for data packet in timeout of 100ms */
token = xchg_spi(0xFF);
} while ((token == 0xFF) && Timer1);
if(token != 0xFE) return 0; /* If not valid data token, retutn with error */
rcvr_spi_multi(buff, btr); /* Receive the data block into buffer */
xchg_spi(0xFF); /* Discard CRC */
xchg_spi(0xFF);
return 1; /* Return with success */
}
/*-----------------------------------------------------------------------*/
/* Send a data packet to MMC */
/*-----------------------------------------------------------------------*/
#if _USE_WRITE
static
int xmit_datablock ( /* 1:OK, 0:Failed */
const BYTE *buff, /* 512 byte data block to be transmitted */
BYTE token /* Data token */
)
{
BYTE resp;
if (!wait_ready()) return 0;
xchg_spi(token); /* Xmit a token */
if (token != 0xFD) { /* Not StopTran token */
xmit_spi_multi(buff, 512); /* Xmit the data block to the MMC */
xchg_spi(0xFF); /* CRC (Dummy) */
xchg_spi(0xFF);
resp = xchg_spi(0xFF); /* Receive a data response */
if ((resp & 0x1F) != 0x05) return 0; /* If not accepted, return with error */
}
return 1;
}
#endif
/*-----------------------------------------------------------------------*/
/* Send a command packet to MMC */
/*-----------------------------------------------------------------------*/
static
BYTE send_cmd (
BYTE cmd, /* Command byte */
DWORD arg /* Argument */
)
{
BYTE n, res;
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
cmd &= 0x7F;
res = send_cmd(CMD55, 0);
if (res > 1) return res;
}
/* Select the card and wait for ready except to stop multiple block read */
if (cmd != CMD12) {
deselect();
if (!select()) return 0xFF;
}
/* Send command packet */
xchg_spi(0x40 | cmd); /* Start + Command index */
xchg_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
xchg_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
xchg_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
xchg_spi((BYTE)arg); /* Argument[7..0] */
n = 0x01; /* Dummy CRC + Stop */
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) + Stop */
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) + Stop */
xchg_spi(n);
/* Receive command response */
if (cmd == CMD12) xchg_spi(0xFF); /* Skip a stuff byte on stop to read */
n = 10; /* Wait for a valid response in timeout of 10 attempts */
do {
res = xchg_spi(0xFF);
} while ((res & 0x80) && --n);
return res; /* Return with the response value */
}
/*--------------------------------------------------------------------------
Public Functions
---------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* Get Disk Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber (0) */
)
{
if (pdrv != 0) return STA_NOINIT; /* Supports only single drive */
return Stat;
}
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber (0) */
)
{
BYTE n, cmd, ty, ocr[4];
if (pdrv != 0) return STA_NOINIT; /* Supports only single drive */
if (Stat & STA_NODISK) return Stat; /* No card in the socket */
power_on(); /* Initialize memory card interface */
FCLK_SLOW();
for (n = 10; n; n--) xchg_spi(0xFF); /* 80 dummy clocks */
ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
Timer1 = 1000; /* Initialization timeout of 1000 msec */
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); /* Get trailing return value of R7 resp */
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
while (Timer1 && send_cmd(ACMD41, 0x40000000)); /* Wait for leaving idle state (ACMD41 with HCS bit) */
if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
ty = (ocr[0] & 0x40) ? CT_SD2|CT_BLOCK : CT_SD2; /* SDv2+ */
}
}
} else { /* SDv1 or MMCv3 */
if (send_cmd(ACMD41, 0) <= 1) {
ty = CT_SD1; cmd = ACMD41; /* SDv1 */
} else {
ty = CT_MMC; cmd = CMD1; /* MMCv3 */
}
while (Timer1 && send_cmd(cmd, 0)); /* Wait for leaving idle state */
if (!Timer1 || send_cmd(CMD16, 512) != 0) ty = 0; /* Set read/write block length to 512 */
}
}
CardType = ty;
deselect();
if (ty) { /* Function succeded */
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
FCLK_FAST();
} else { /* Function failed */
power_off(); /* Deinitialize interface */
}
return Stat;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
DWORD sector, /* Start sector number (LBA) */
UINT count /* Sector count (1..128) */
)
{
if (pdrv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
if (count == 1) { /* Single block read */
if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
&& rcvr_datablock(buff, 512)) {
count = 0;
}
}
else { /* Multiple block read */
if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
do {
if (!rcvr_datablock(buff, 512)) break;
buff += 512;
} while (--count);
send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
}
}
deselect();
return count ? RES_ERROR : RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if _USE_WRITE
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber (0) */
const BYTE *buff, /* Pointer to the data to be written */
DWORD sector, /* Start sector number (LBA) */
UINT count /* Sector count (1..128) */
)
{
if (pdrv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (Stat & STA_PROTECT) return RES_WRPRT;
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
if (count == 1) { /* Single block write */
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
&& xmit_datablock(buff, 0xFE)) {
count = 0;
}
}
else { /* Multiple block write */
if (CardType & CT_SDC) send_cmd(ACMD23, count);
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
do {
if (!xmit_datablock(buff, 0xFC)) break;
buff += 512;
} while (--count);
if (!xmit_datablock(0, 0xFD)) count = 1; /* STOP_TRAN token */
}
}
deselect();
return count ? RES_ERROR : RES_OK;
}
#endif
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
#if _USE_IOCTL
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive data block */
)
{
DRESULT res;
BYTE n, csd[16], *ptr = buff;
DWORD csz;
if (pdrv) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
res = RES_ERROR;
switch (cmd) {
case CTRL_SYNC : /* Flush write-back cache, Wait for end of internal process */
if (select()) res = RES_OK;
break;
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (WORD) */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
if ((csd[0] >> 6) == 1) { /* SDv2? */
csz = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;
*(DWORD*)buff = csz << 10;
} else { /* SDv1 or MMCv3 */
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
csz = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
*(DWORD*)buff = csz << (n - 9);
}
res = RES_OK;
}
break;
case GET_BLOCK_SIZE : /* Get erase block size in unit of sectors (DWORD) */
if (CardType & CT_SD2) { /* SDv2+? */
if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */
xchg_spi(0xFF);
if (rcvr_datablock(csd, 16)) { /* Read partial block */
for (n = 64 - 16; n; n--) xchg_spi(0xFF); /* Purge trailing data */
*(DWORD*)buff = 16UL << (csd[10] >> 4);
res = RES_OK;
}
}
} else { /* SDv1 or MMCv3 */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */
if (CardType & CT_SD1) { /* SDv1 */
*(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
} else { /* MMCv3 */
*(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
}
res = RES_OK;
}
}
break;
case MMC_GET_TYPE : /* Get card type flags (1 byte) */
*ptr = CardType;
res = RES_OK;
break;
case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
if ((send_cmd(CMD9, 0) == 0) /* READ_CSD */
&& rcvr_datablock(buff, 16))
res = RES_OK;
break;
case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
if ((send_cmd(CMD10, 0) == 0) /* READ_CID */
&& rcvr_datablock(buff, 16))
res = RES_OK;
break;
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
for (n = 0; n < 4; n++)
*((BYTE*)buff+n) = xchg_spi(0xFF);
res = RES_OK;
}
break;
case MMC_GET_SDSTAT : /* Receive SD statsu as a data block (64 bytes) */
if ((CardType & CT_SD2) && send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
xchg_spi(0xFF);
if (rcvr_datablock(buff, 64)) res = RES_OK;
}
break;
case CTRL_POWER_OFF : /* Power off */
power_off();
Stat |= STA_NOINIT;
res = RES_OK;
break;
default:
res = RES_PARERR;
}
deselect();
return res;
}
#endif
/*-----------------------------------------------------------------------*/
/* Device Timer Driven Procedure */
/*-----------------------------------------------------------------------*/
/* This function must be called by timer interrupt in period of 1ms */
void disk_timerproc (void)
{
BYTE s;
UINT n;
n = Timer1; /* 1000Hz decrement timer with zero stopped */
if (n) Timer1 = --n;
n = Timer2;
if (n) Timer2 = --n;
/* Update socket status */
s = Stat;
if (MMC_WP) {
s |= STA_PROTECT;
} else {
s &= ~STA_PROTECT;
}
if (MMC_CD) {
s &= ~STA_NODISK;
} else {
s |= (STA_NODISK | STA_NOINIT);
}
Stat = s;
}
+34
View File
@@ -0,0 +1,34 @@
/*
* File: ChaletPowerRelay.h
* Author: JF
*
* Created on November 30, 2018, 7:33 PM
*/
#ifndef FLASHMAPPING_H
#define FLASHMAPPING_H
#include "define.h"
/*
0x180000 Firmware flags
0x180004 Nb Records
0x180008 Firmware Size
0x18000C Version code
*/
#define FLASH_END_ADDRESS 180000
#define FLASH_BTLDR_FIRMWARE_START_ADDRESS 0x180000
#define FLASH_BTLDR_FIRMWARE_LAST_64K_SECTOR_ADD 0x1F0000
#define FLASH_BTLDR_FLAGS_ADDRESS 0x000000
#define FLASH_WIFI_IP_ADDRESS 0X00000C
#define FLASH_WIFI_GATEWAY_ADDRESS 0x000010
#define FLASH_BTLDR_HEADER_SIZE 24
#endif /* HARAKIRIRELAY_H */
+6
View File
@@ -0,0 +1,6 @@
#include "BoardCfg.h"
int InitBoard()
{
return RET_OK;
}
+21
View File
@@ -0,0 +1,21 @@
//#include <proc/p32mx440f256h.h>
#include "HarakiriRelay.h"
#include "BoardCfg.h"
#include "timer.h"
#define PIN_ACTIVE 1
#define PIN_INACTIVE 0
void InitHarakiriRelay()
{
HARAKIRI_RELAY_ON_PIN = PIN_INACTIVE; //Very important!!
}
bool HarakiriRelayTurnOff()
{
HARAKIRI_RELAY_ON_PIN = PIN_ACTIVE; //Just wait for the power to be killed...
return true;
}
+19
View File
@@ -0,0 +1,19 @@
/*
* File: ChaletPowerRelay.h
* Author: JF
*
* Created on November 30, 2018, 7:33 PM
*/
#ifndef HARAKIRIRELAY_H
#define HARAKIRIRELAY_H
#include "define.h"
void InitHarakiriRelay();
bool HarakiriRelayTurnOff();
#endif /* HARAKIRIRELAY_H */
+171
View File
@@ -0,0 +1,171 @@
#include "define.h"
#include "BoardCfg.h"
#include "I2C.h"
int mLastTransactionOK;
int mI2CWaitCounter;
int I2CInit()
{
//SPI and I2C BRG work the same way. So let's reuse some code!
// int BaudRateGenerator = SPICalculateBRG(80000000,100000); //PBclk is 80MHz, I2C clk = 100KHz
int BaudRateGenerator = 398;
I2C3CON = 0;
I2C3CONbits.DISSLW = 1; //disable slew rate control since we are only at 100KHz
I2C3BRG = BaudRateGenerator;
I2C3CONbits.ON = 1;
mLastTransactionOK = 0;
mI2CWaitCounter = 0;
}
int I2CWrite(unsigned char* OutBuf, unsigned char length)
{
int RET = RET_OK;
int i;
//Emit start event
I2C3CONbits.SEN = 1;
while(I2C3CONbits.SEN == 1)
{
}
if(I2C3STATbits.BCL == 1)
{
mLastTransactionOK = false;
return RET_ERROR;
}
for(i = 0; i < length; i++)
{
I2C3TRN = OutBuf[i];
mI2CWaitCounter = 0;
while(I2C3STATbits.TRSTAT == 1)
{
if(I2C3STATbits.BCL == 1 || mI2CWaitCounter++ > I2C_TRANSACTION_TIMEOUT_COUNT)
{
mLastTransactionOK = false;
RET = RET_ERROR;
break;
}
}
// if(I2C3STATbits.ACKSTAT == 1)
// {
// RET = RET_ERROR;
// }
}
//Emit stop event
I2C3CONbits.PEN = 1;
mI2CWaitCounter = 0;
while(I2C3CONbits.PEN == 1)
{
if(I2C3STATbits.BCL == 1 || mI2CWaitCounter++ > I2C_TRANSACTION_TIMEOUT_COUNT)
{
mLastTransactionOK = false;
RET = RET_ERROR;
break;
}
}
mLastTransactionOK = true;
return RET;
}
int I2CTransmitByte(unsigned char Byte)
{
return RET_ERROR;
}
int I2CRead(unsigned char SlaveAddress,unsigned char* InputBuf,unsigned char length)
{
int RET = RET_OK;
int i;
//Emit start event
I2C3CONbits.SEN = 1;
mI2CWaitCounter = 0;
while(I2C3CONbits.SEN == 1)
if(I2C3STATbits.BCL == 1)
{
mLastTransactionOK = false;
return RET_ERROR;
}
//Transmit slave address and write bit
I2C3TRN = SlaveAddress;
mI2CWaitCounter = 0;
while(I2C3STATbits.TRSTAT == 1)
{
if(I2C3STATbits.BCL == 1 || mI2CWaitCounter++ > I2C_TRANSACTION_TIMEOUT_COUNT)
{
mLastTransactionOK = false;
return RET_ERROR;
}
}
for(i = 0; i < length; i++)
{
//
I2C3CONbits.RCEN = 1;
mI2CWaitCounter = 0;
while(I2C3CONbits.RCEN == 1)
{
if(I2C3STATbits.BCL == 1 || mI2CWaitCounter++ > I2C_TRANSACTION_TIMEOUT_COUNT)
{
mLastTransactionOK = false;
return RET_ERROR;
}
}
InputBuf[i] = I2C3RCV;
//Acknowledge reception
I2C3CONbits.ACKDT = 1;
I2C3CONbits.ACKEN = 1;
mI2CWaitCounter = 0;
while(I2C3CONbits.ACKEN == 1)
{
if(I2C3STATbits.BCL == 1 || mI2CWaitCounter++ > I2C_TRANSACTION_TIMEOUT_COUNT)
{
mLastTransactionOK = false;
return RET_ERROR;
}
}
}
//Emit stop event
I2C3CONbits.PEN = 1;
mI2CWaitCounter = 0;
while(I2C3CONbits.PEN == 1)
{
if(I2C3STATbits.BCL == 1 || mI2CWaitCounter++ > I2C_TRANSACTION_TIMEOUT_COUNT)
{
mLastTransactionOK = false;
return RET_ERROR;
}
}
mLastTransactionOK = true;
return RET;
}
bool I2CWasLastTransactionOK()
{
return mLastTransactionOK;
}
+21
View File
@@ -0,0 +1,21 @@
/*
* File: SPI.h
* Author: JF
*
* Created on December 2, 2018, 3:36 PM
*/
#ifndef I2C_H
#define I2C_H
#define I2C_BUFSIZE 10
#define I2C_TRANSACTION_TIMEOUT_COUNT 800000 //around 10ms
int I2CInit();
int I2CWrite(unsigned char* OutBuf, unsigned char length);
int I2CRead(unsigned char SlaveAddress, unsigned char* InputBuf,unsigned char length);
bool I2CWasLastTransactionOK();
#endif /* SPI_H */
+597
View File
@@ -0,0 +1,597 @@
/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C code file.
*/
/* ************************************************************************** */
/* ¤Revision:
000 20100616 JFM,
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
/* ************************************************************************** */
/* Includes */
#include "define.h"
#include "InternalUart.h"
#include "uart.h"
#include <stdio.h>
//#include "Watchdog.h"
#include "digitalio.h"
#include "NetworkProtocol.h"
/* ************************************************************************** */
/* Local variables */
char acIntUartRxBuff[MAX_INTERNAL_UART_PORT][INTERNAL_UART_BUFFER_DEPTH]; //Rx Buffers
stInternalUartData astInternalUartData[MAX_INTERNAL_UART_PORT]; //port management data
unsigned int LoraData = 0;
void process(void);
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void InternalUartInit(void)
{
//Setup port 1
//
// U1MODEbits.ON = 0; //disable module
// U1STA = 0;
// U1STAbits.UTXEN = 0; //disable transmitter
// IPC6bits.U1IP = 7; //priority 7
// IPC6bits.U1IS = 3; //sub-priority 3
// U1STAbits.UTXSEL = 0b01; //interrupt when all characters are transmitted
//// U1STAbits.UTXSEL = 0b01; // //JFM 2012-08-27
// IFS0bits.U1TXIF = 0; //clear interrupt flag
// IEC0bits.U1TXIE = 1; //enable tx interrupt
// U1STAbits.URXISEL = 0b00; //interrupt for each character received
// IFS0bits.U1RXIF = 0;
//#ifdef POLL_UART1_RX
// IEC0bits.U1RXIE = 0; //disable rx interrupts
//#else
// IEC0bits.U1RXIE = 1; //enable rx interrupts
//#endif
// U1STAbits.URXEN = 1; //enable receiver
// U1MODEbits.ON = 0; //disable module
//Setup port 2
//
U2MODEbits.ON = 0; //disable module
U2STA = 0;
U2STAbits.UTXEN = 0; //disable transmitter
IPC8bits.U2IP = 7; //priority 7
IPC8bits.U2IS = 0; //sub-priority 2
U2STAbits.UTXSEL = 0b01; //interrupt when all characters are transmitted
IFS1bits.U2TXIF = 0; //clear interrupt flag
IEC1bits.U2TXIE = 0; //enable tx interrupt
U2STAbits.URXISEL = 0b00; //interrupt for each character received
IFS1bits.U2RXIF = 0;
#ifdef POLL_UART2_RX
IEC1bits.U2RXIE = 0; //disable rx interrupts
#else
IEC1bits.U2RXIE = 1; //enable rx interrupts
#endif
U2STAbits.URXEN = 1; //enable receiver
U2STAbits.UTXEN = 1;
U2MODEbits.ON = 0; //disable module
int i;
for(i = 0; i < MAX_INTERNAL_UART_PORT; i++)
{
astInternalUartData[i].pcTxDataPtr = 0;
astInternalUartData[i].iNbFIFOPendingBytes = 0;
astInternalUartData[i].iTxDataSize = 0;
astInternalUartData[i].iTxDataCounter = 0;
astInternalUartData[i].iIsBusy = 0;
astInternalUartData[i].iIsOpened = 0;
astInternalUartData[i].iUartHandle = 0;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//int SetIntalUartInterrupts(int p_iUartPort, int p_iRxInterrupt,int p_iTxInterrupt)
//{
// if(p_iUartPort > MAX_INTERNAL_UART_PORT)
// return UART_INVALID_PORT;
//
// switch(p_iUartPort)
// {
// case INTERNAL_UART_PORT_1:
// {
// if(p_iTxInterrupt)
// {
// IFS0bits.U1TXIF = 0; //clear interrupt flag
// IEC0bits.U1TXIE = 1; //enable tx interrupt
// }
// else
// {
// IEC0bits.U1TXIE = 0; //disable tx interrupt
// U1STAbits.UTXEN = 1; //This bit must be set when working without interrupts
// }
// if(p_iRxInterrupt)
// {
// IFS0bits.U1RXIF = 0;
// IEC0bits.U1RXIE = 1; //enable rx interrupt
// }
// else
// {
// IEC0bits.U1RXIE = 0; //disable rx interrupt
// }
// break;
// }
// case INTERNAL_UART_PORT_2:
// {
// if(p_iTxInterrupt)
// {
// IFS1bits.U2TXIF = 0; //clear interrupt flag
// IEC1bits.U2TXIE = 1; //enable tx interrupt
// }
// else
// {
// IEC1bits.U2TXIE = 0; //disable tx interrupt
// U2STAbits.UTXEN = 1; //This bit must be set when working without interrupts
// }
// if(p_iRxInterrupt)
// {
// IFS1bits.U2RXIF = 0;
// IEC1bits.U2RXIE = 1; //enable rx interrupt
// }
// else
// {
// IEC1bits.U2RXIE = 0; //disable rx interrupt
// }
// break;
// }
// default:
// {
// return UART_INVALID_PORT;
// }
// }
// return UART_OK;
//}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int OpenInternalPort(int p_iUartPort,int p_iUartHandle,char *p_pcHeadPtr, char *p_pcTailPtr, int p_iBaudRate, int p_iNbStopBits, int p_iParityEnable)
{
if(p_iUartPort > MAX_INTERNAL_UART_PORT)
return UART_INVALID_PORT;
int iBRG = (PERIPHERAL_FREQ/(4*p_iBaudRate)) - 1;
int iMask = 0;
switch(p_iNbStopBits)
{
case INT_UART_ONE_STOP_BIT:
{
break;
}
case INT_UART_TWO_STOP_BITS:
{
iMask |= 0x00000001;
break;
}
}
astInternalUartData[p_iUartPort].iUartHandle = p_iUartHandle;
switch(p_iParityEnable)
{
case INT_UART_NO_PARITY:
{
break;
}
case INT_UART_EVEN_PARITY:
{
iMask |= 0x00000002;
break;
}
case INT_UART_ODD_PARITY:
{
iMask |= 0x00000004;
break;
}
}
switch(p_iUartPort)
{
case INTERNAL_UART_PORT_1:
{
INTERNAL_UART1_TX_PIN_DIR = PIN_OUTPUT;
INTERNAL_UART1_TX_PIN = 1;
U1MODE = iMask;
U1MODEbits.BRGH = 1;
U1BRG = iBRG;
U1MODEbits.ON = 1; //enable module
break;
}
case INTERNAL_UART_PORT_2:
{
INTERNAL_UART2_TX_PIN_DIR = PIN_OUTPUT;
INTERNAL_UART2_TX_PIN = 1;
U2MODE = iMask;
U2MODEbits.BRGH = 1;
U2BRG = iBRG;
U2MODEbits.ON = 1; //enable module
break;
}
}
astInternalUartData[p_iUartPort].iIsOpened = 1;
return UART_OK;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int SendInternalUartData(char *p_pcDataBuf, int p_iDataSize, int p_iUartPort, char *p_pcSourceBufferHead, char *p_pcSourceBufferTail)
{
int iBufSize;
int iAvailableBufSize;
char *p_cDataPointer;
int i;
stInternalUartData *p_stUartDataPtr = &astInternalUartData[p_iUartPort];
if(p_stUartDataPtr->iIsOpened == 0)
return UART_PORT_NOT_OPENED;
//We use a FIFO stack that must be empty before a new transaction can occur
//if(p_stUartDataPtr->iNbFIFOPendingBytes != 0) //If FIFO not empty
if(p_stUartDataPtr->iIsBusy == 1)
return UART_PORT_BUSY; //no space is available so flag the port as BUSY...
iBufSize = p_iDataSize;
if(iBufSize > INTERNAL_UART_BUFFER_DEPTH)
iBufSize = INTERNAL_UART_BUFFER_DEPTH;
p_cDataPointer = p_stUartDataPtr->pcTxDataPtr = &p_stUartDataPtr->acIntUartTxFIFO[0];
p_stUartDataPtr->iNbFIFOPendingBytes = iBufSize;
//Fill FIFO with data;
for(i = 0; i< iBufSize; i++)
{
*p_cDataPointer++ = *p_pcDataBuf++;
if(p_pcDataBuf > p_pcSourceBufferTail) //check for wrapping of source data circular buffer.
p_pcDataBuf = p_pcSourceBufferHead;
}
p_stUartDataPtr->iIsBusy = 1; //informative flag to know we are TXing.
//Begin Transmission
//A TX interrupt will be generated immediately after setting UTXEN
switch(p_iUartPort)
{
case INTERNAL_UART_PORT_1:
{
if(IEC0bits.U1TXIE)
{
//We consider at this point that the data has been sent for the upper layer.
DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize);
U1STAbits.UTXEN = 1;
}
else
{
int i;
for(i = 0; i < iBufSize; i++)
{
// KickWatchdog();
U1TXREG = *p_stUartDataPtr->pcTxDataPtr++;
while(U1STAbits.TRMT == 0);
}
p_stUartDataPtr->iIsBusy = 0;
DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize);
}
break;
}
case INTERNAL_UART_PORT_2:
{
if(IEC1bits.U2TXIE)
{
//We consider at this point that the data has been sent for the upper layer.
DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize);
U2STAbits.UTXEN = 1;
}
else
{
int i;
for(i = 0; i < iBufSize; i++)
{
// KickWatchdog();
U2TXREG = *p_stUartDataPtr->pcTxDataPtr++;
while(U2STAbits.TRMT == 0);
LORA_MODULE_TX_LED_PIN = ~ LORA_MODULE_TX_LED_PIN;
}
p_stUartDataPtr->iIsBusy = 0;
DataSentNotification(p_stUartDataPtr->iUartHandle,iBufSize);
}
break;
}
}
return UART_OK;
}
int SendInternalUartDataBlocking(char *p_pcDataBuf, int p_iDataSize, int p_iUartPort)
{
int i;
int temp = IEC1;
IEC1bits.U2TXIE = 0;
for(i = 0; i < p_iDataSize; i++)
{
LORA_MODULE_TX_LED_PIN = ~ LORA_MODULE_TX_LED_PIN;
U2TXREG = *p_pcDataBuf++;
while(U2STAbits.TRMT == 0);
}
LORA_MODULE_TX_LED_PIN = LED_OFF;
IFS1bits.U2TXIF = 0;
IEC1 = temp;
return UART_OK;
}
void TickInternalUart(void)
{
#ifdef POLL_UART1_RX
if(U1STAbits.URXDA == 1)
{
if(U1STAbits.OERR) //Buffer overrun error. Data is lost.
{
U1STAbits.OERR = 0;
}
int i = 0;
while(U1STAbits.URXDA && i < INTERNAL_UART_BUFFER_DEPTH)
{
char NewByte = U1RXREG;
// DriveProtocolRxData(&NewByte,1);
acIntUartRxBuff[INTERNAL_UART_PORT_1][i++] = NewByte;
}
// UartReceiveData(UART_1,&acIntUartRxBuff[INTERNAL_UART_PORT_1][0], i);
// DriveProtocolRxData(&acIntUartRxBuff[INTERNAL_UART_PORT_1][0], i);
}
#endif
#ifdef POLL_UART2_RX
if(U2STAbits.URXDA == 1)
{
int i = 0;
while(U2STAbits.URXDA == 1 && i < INTERNAL_UART_BUFFER_DEPTH)
{
char NewByte = U2RXREG;
// acIntUartRxBuff[INTERNAL_UART_PORT_2][i++] = NewByte;
LORA_MODULE_RX_LED_PIN = ~LORA_MODULE_RX_LED_PIN;
ProtocolAnalyzeNewData(NewByte);
// LoraData <<= 8;
// unsigned int toto = NewByte;
// toto &= 0x000000FF;
// LoraData |= toto;
//
// if(LoraData == 0xDEADBEEF)
// {
// HEARTBEAT_LED_1_PIN = ~HEARTBEAT_LED_1_PIN;
// LORA_ACTIVITY_LED_PIN = ~LORA_ACTIVITY_LED_PIN;
// LoraData = 0;
// }
// HEARTBEAT_LED_2_PIN = ~HEARTBEAT_LED_2_PIN;
}
if(U2STAbits.OERR) //Buffer overrun error. Data is lost.
{
U2STAbits.OERR = 0;
printf("Overrun\n");
}
// UartReceiveData(UART_2,&acIntUartRxBuff[INTERNAL_UART_PORT_2][0], i);
// CUProtocolRxData(&acIntUartRxBuff[INTERNAL_UART_PORT_2][0], i);
}
#endif
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void __ISR(_UART_1_VECTOR, ipl7) InternalUart1AInterrupt(void)
{
stInternalUartData *p_acUartDataPtr = &astInternalUartData[INTERNAL_UART_PORT_1];
if(IFS0bits.U1TXIF && IEC0bits.U1TXIE)
{
IFS0bits.U1TXIF = 0;
//Check if there is still data to send in FIFO
if(p_acUartDataPtr->iNbFIFOPendingBytes == 0)
{
U1STAbits.UTXEN = 0; //all data sent, stop transmitter
p_acUartDataPtr->iIsBusy = 0;
}
else
{
do
{
U1TXREG = *p_acUartDataPtr->pcTxDataPtr++; //send data
p_acUartDataPtr->iNbFIFOPendingBytes--;
}
while((U1STAbits.UTXBF == 0) && //while there is space in buffer
(p_acUartDataPtr->iNbFIFOPendingBytes != 0)); //and data to send
// HCAM
// if(p_acUartDataPtr->iNbFIFOPendingBytes == 0)
// {
// // U1STAbits.UTXEN = 0; //all data sent, stop transmitter
// p_acUartDataPtr->iIsBusy = 0;
// }
}
}
if(IFS0bits.U1RXIF && IEC0bits.U1RXIE)
{
char NewByte;
int i;
IFS0bits.U1RXIF = 0;
if(U1STAbits.OERR) //Buffer overrun error. Data is lost.
{
U1STAbits.OERR = 0;
IFS0bits.U1RXIF = 0;
printf("UART1 OERR\n");
return;
}
i = 0;
while(U1STAbits.URXDA)
{
NewByte = U1RXREG;
acIntUartRxBuff[INTERNAL_UART_PORT_1][i++] = NewByte;
}
UartReceiveData(p_acUartDataPtr->iUartHandle,&acIntUartRxBuff[INTERNAL_UART_PORT_1][0], i);
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void __ISR(_UART_2_VECTOR, ipl7) InternalUart2Interrupt(void)
{
stInternalUartData *p_acUartDataPtr = &astInternalUartData[INTERNAL_UART_PORT_2];
if(IFS1bits.U2TXIF && IEC1bits.U2TXIE)
{
IFS1bits.U2TXIF = 0;
//Check if there is still data to send in FIFO
if(p_acUartDataPtr->iNbFIFOPendingBytes == 0)
{
U2STAbits.UTXEN = 0; //all data sent, stop transmitter
p_acUartDataPtr->iIsBusy = 0;
//LORA_MODULE_TX_LED_PIN = LED_OFF;
}
else
{
do
{
U2TXREG = *p_acUartDataPtr->pcTxDataPtr++; //send data
p_acUartDataPtr->iNbFIFOPendingBytes--;
LORA_MODULE_TX_LED_PIN = ~ LORA_MODULE_TX_LED_PIN;
}
while((U2STAbits.UTXBF == 0) && //while there is space in buffer
(p_acUartDataPtr->iNbFIFOPendingBytes != 0)); //and data to send
}
}
if(IFS1bits.U2RXIF && IEC1bits.U2RXIE)
{
IFS1bits.U2RXIF = 0;
char NewByte;
int i;
if(U2STAbits.OERR) //Buffer overrun error. Data is lost.
{
U2STAbits.OERR = 0;
IFS1bits.U2RXIF = 0;
printf("UART2 OERR\n");
return;
}
i = 0;
while(U2STAbits.URXDA)
{
NewByte = U2RXREG;
acIntUartRxBuff[INTERNAL_UART_PORT_2][i++] = NewByte;
LORA_MODULE_RX_LED_PIN = ~LORA_MODULE_RX_LED_PIN;
}
UartReceiveData(p_acUartDataPtr->iUartHandle,&acIntUartRxBuff[INTERNAL_UART_PORT_2][0], i);
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Resets UART1 without closing it. Used when comm crashes.
void ResetUart1(void)
{
U1MODEbits.ON = 0; //disable module
U1STAbits.UTXEN = 0; //disable transmitter
IEC0bits.U1TXIE = 0; //disable tx interrupt
IFS0bits.U1TXIF = 0; //clear interrupt flag
IEC0bits.U1TXIE = 1; //enable tx interrupt
IEC0bits.U1RXIE = 0; //disable rx interrupts
IEC0bits.U1RXIE = 0; //disable rx interrupts
IFS0bits.U1RXIF = 0;
#ifdef POLL_UART1_RX
IEC0bits.U1RXIE = 0; //disable rx interrupts
#else
IEC0bits.U1RXIE = 1; //enable rx interrupts
#endif
U1STAbits.URXEN = 1; //enable receiver
astInternalUartData[INTERNAL_UART_PORT_1].pcTxDataPtr = &astInternalUartData[INTERNAL_UART_PORT_1].acIntUartTxFIFO[0];
astInternalUartData[INTERNAL_UART_PORT_1].iTxDataSize = 0;
astInternalUartData[INTERNAL_UART_PORT_1].iIsBusy = 0;
U1MODEbits.ON = 1; //enable module
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void ResetUart2(void)
{
//Setup port 2
//
U2MODEbits.ON = 0; //disable module
U2STAbits.UTXEN = 0; //disable transmitter
IEC1bits.U2TXIE = 0; //disable tx interrupt
IFS1bits.U2TXIF = 0; //clear interrupt flag
IEC1bits.U2TXIE = 0; //enable tx interrupt
IEC1bits.U2RXIE = 0; //disable rx interrupts
IFS1bits.U2RXIF = 1;
#ifdef POLL_UART2_RX
IEC1bits.U2RXIE = 0; //disable rx interrupts
#else
IEC1bits.U2RXIE = 1; //enable rx interrupts
#endif
U2STAbits.URXEN = 1; //enable receiver
astInternalUartData[INTERNAL_UART_PORT_2].pcTxDataPtr = &astInternalUartData[INTERNAL_UART_PORT_2].acIntUartTxFIFO[0];
astInternalUartData[INTERNAL_UART_PORT_2].iTxDataSize = 0;
astInternalUartData[INTERNAL_UART_PORT_2].iIsBusy = 0;
U2MODEbits.ON = 1; //disable module
}
//-----------------------------------------------------------------------------
void process(void)
{
}
//EOF
+98
View File
@@ -0,0 +1,98 @@
/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C header file.
*/
/* ************************************************************************** */
/* ¤Revision:
000 20100616 JFM,
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
#ifndef INTERNAL_UART_H
#define INTERNAL_UART_H
/* ************************************************************************** */
/* Includes */
/* ************************************************************************** */
/* Defines */
#define INTERNAL_UART_BUFFER_DEPTH 1//4//16 //JFM 2012-08-27
#define USE_TX_INTERNAL_BUFFER
#define INTERNAL_UART1_TX_PIN_DIR TRISFbits.TRISF3
#define INTERNAL_UART1_TX_PIN LATFbits.LATF3
#define INTERNAL_UART2_TX_PIN_DIR TRISFbits.TRISF5
#define INTERNAL_UART2_TX_PIN LATFbits.LATF5
/* ************************************************************************** */
/* Type definitions */
typedef enum
{
INTERNAL_UART_PORT_1,
INTERNAL_UART_PORT_2,
MAX_INTERNAL_UART_PORT
}eInternalUartPorts;
typedef enum
{
INT_UART_NO_PARITY,
INT_UART_EVEN_PARITY,
INT_UART_ODD_PARITY
}eIntUartParity;
typedef enum
{
INT_UART_ONE_STOP_BIT,
INT_UART_TWO_STOP_BITS
}eIntUartStopBits;
typedef enum
{
INT_UART_INTERRUPT_OFF,
INT_UART_INTERRUPT_ON
}eIntUartInterruptOnOff;
typedef struct
{
char *pcTxDataPtr;
char acIntUartTxFIFO[INTERNAL_UART_BUFFER_DEPTH];
int iNbFIFOPendingBytes;
int iTxDataSize;
int iTxDataCounter;
int iIsBusy;
int iIsOpened;
int iUartHandle;
}stInternalUartData;
/* ************************************************************************** */
/* Prototypes */
void InternalUartInit(void);
int OpenInternalPort(int p_iUartPort,int p_iUartHandle,char *p_pcHeadPtr, char *p_pcTailPtr, int p_iBaudRate, int p_iNbStopBits, int p_iParityEnable);
int SendInternalUartData(char *p_pcDataBuf, int p_iDataSize, int p_iUartPort, char *p_pcSourceBufferHead, char *p_pcSourceBufferTail);
int SetIntalUartInterrupts(int p_iUartPort, int p_iRxInterrupt,int p_iTxInterrupt);
int SendInternalUartDataBlocking(char *p_pcDataBuf, int p_iDataSize, int p_iUartPort);
void TickInternalUart(void);
void ResetUart1(void);
void ResetUart2(void);
#endif
//EOF
+123
View File
@@ -0,0 +1,123 @@
//#include <proc/p32mx440f256h.h>
#include "KnobEncoderCtrl.h"
#include "BoardCfg.h"
#include "LedLightCtrl.h"
#include "timer.h"
bool KnobDebounce;
int KnobReadSM = KEC_WAIT_FOR_TRIGGER_STATE;
#define PIN_ACTIVE 0
#define PIN_INACTIVE 1
//bool KnobDebounce;
//void __ISR(_EXTERNAL_1_VECTOR , ipl2) KnobEncoderInterrupt(void)
//{
// if(KnobDebounce == false)
// {
// int dir = KNOB_PH_B_PIN;
//
// KnobDebounce = true;
// TimerStart(KNOB_DEBOUNCE_TIMER,KNOB_DEBOUNCE_TIMEOUT);
// IEC0bits.INT1IE = 0;
//
// if(dir == 1)
// {
// LedLightIncrease();
// }
// else
// {
// LedLightDecrease();
// }
// }
//
// IFS0bits.INT1IF = 0;
//}
void KnobDebounceCtrlSM()
{
switch(KnobReadSM)
{
case KEC_CHECK_BTN_STATE:
{
if(KNOB_TGLE_BTN_PIN == PIN_ACTIVE)
{
LedLightONOFFBtnPressed();
KnobReadSM = KEC_DEBOUNCE_BTN_STATE;
TimerStart(KNOB_DEBOUNCE_TIMER,250);
}
else
{
KnobReadSM = KEC_WAIT_FOR_TRIGGER_STATE;
}
break;
}
case KEC_DEBOUNCE_BTN_STATE:
{
if(IsTimerExpired(KNOB_DEBOUNCE_TIMER))
{
KnobReadSM = KEC_WAIT_FOR_BTN_RST_STATE;
}
break;
}
case KEC_WAIT_FOR_BTN_RST_STATE:
{
if(KNOB_TGLE_BTN_PIN == PIN_INACTIVE)
{
KnobReadSM = KEC_WAIT_FOR_TRIGGER_STATE;
}
break;
}
case KEC_WAIT_FOR_TRIGGER_STATE:
{
if(KNOB_PH_A_PIN == PIN_ACTIVE)
{
if(KNOB_PH_B_PIN == PIN_ACTIVE)
{
LedLightIncrease();
}
else
{
LedLightDecrease();
}
TimerStart(KNOB_DEBOUNCE_TIMER,KNOB_DEBOUNCE_TIMEOUT);
KnobReadSM = KEC_DEBOUNCE_STATE;
}
else
{
KnobReadSM = KEC_CHECK_BTN_STATE;
}
break;
}
case KEC_DEBOUNCE_STATE:
{
if(IsTimerExpired(KNOB_DEBOUNCE_TIMER))
{
KnobReadSM = KEC_WAIT_FOR_RESET_STATE;
}
break;
}
case KEC_WAIT_FOR_RESET_STATE:
{
if((KNOB_PH_A_PIN == PIN_INACTIVE))
{
if(KNOB_PH_B_PIN == PIN_INACTIVE)
{
TimerStart(KNOB_DEBOUNCE_TIMER,KNOB_DEBOUNCE_TIMEOUT);
KnobReadSM = KEC_WAIT_A_LITTLE_MORE_STATE;
}
}
break;
}
case KEC_WAIT_A_LITTLE_MORE_STATE:
{
if(IsTimerExpired(KNOB_DEBOUNCE_TIMER))
{
KnobReadSM = KEC_CHECK_BTN_STATE;
}
break;
}
}
}
+31
View File
@@ -0,0 +1,31 @@
/*
* File: KnobEncoderCtrl.h
* Author: JF
*
* Created on November 30, 2018, 7:33 PM
*/
#ifndef KNOBENCODERCTRL_H
#define KNOBENCODERCTRL_H
#include "define.h"
#define KNOB_DEBOUNCE_TIMEOUT 5 //ms
void KnobDebounceCtrlSM();
enum KnobEncoderCtrlSMStates
{
KEC_CHECK_BTN_STATE,
KEC_DEBOUNCE_BTN_STATE,
KEC_WAIT_FOR_BTN_RST_STATE,
KEC_WAIT_FOR_TRIGGER_STATE,
KEC_DEBOUNCE_STATE,
KEC_WAIT_FOR_RESET_STATE,
KEC_WAIT_A_LITTLE_MORE_STATE
};
#endif /* KNOBENCODERCTRL_H */
+96
View File
@@ -0,0 +1,96 @@
#include "define.h"
#include "LedLightCtrl.h"
#include "PWMCtrl.h"
int LedLightBrightness = 10;
int LedLightState = LED_LIGHT_ON;
void LedLightDecrease()
{
if(LedLightState == LED_LIGHT_OFF)
return;
LedLightDim(LED_LIGHT_TICK_STEP);
}
void LedLightDim(int Percent)
{
if(LedLightState == LED_LIGHT_OFF)
return;
LedLightBrightness -= Percent;
if(LedLightBrightness < LED_LIGHT_MIN_DIM_VAL)
{
LedLightBrightness = LED_LIGHT_MIN_DIM_VAL;
}
PWMSetValue(LedLightBrightness);
}
void LedLightBright(int Percent)
{
if(LedLightState == LED_LIGHT_OFF)
return;
LedLightBrightness += Percent;
if(LedLightBrightness >= 100)
{
LedLightBrightness = 100;
}
PWMSetValue(LedLightBrightness);
}
void LedLightIncrease()
{
if(LedLightState == LED_LIGHT_OFF)
return;
LedLightBright(LED_LIGHT_TICK_STEP);
}
void LedLightSet(int Percent)
{
if(Percent < 0)
Percent = 0;
if(Percent > 100)
Percent = 100;
LedLightBrightness = Percent;
PWMSetValue(LedLightBrightness);
}
void TurnLedLightON()
{
LedLightState = LED_LIGHT_ON;
PWMSetValue(LedLightBrightness);
}
void TurnLedLightOFF()
{
LedLightState = LED_LIGHT_OFF;
PWMSetValue(0);
}
void LedLightONOFFBtnPressed()
{
if(LedLightState == LED_LIGHT_ON)
{
TurnLedLightOFF();
}
else
{
TurnLedLightON();
}
}
int GetLedLightBrightness()
{
return LedLightBrightness;
}
int GetLedLightState()
{
return LedLightState;
}
+33
View File
@@ -0,0 +1,33 @@
/*
* File: LedLightCtrl.h
* Author: JF
*
* Created on November 30, 2018, 8:09 PM
*/
#ifndef LEDLIGHTCTRL_H
#define LEDLIGHTCTRL_H
#define LED_LIGHT_TICK_STEP 5 //Percent
#define LED_LIGHT_MIN_DIM_VAL 10 //Percent
#define LED_LIGHT_ON 1
#define LED_LIGHT_OFF 0
extern int LedLightBrightness;
void LedLightDim(int Percent);
void LedLightDecrease();
void LedLightBright(int Percent);
void LedLightIncrease();
void LedLightSet(int Percent);
void LedLightONOFFBtnPressed();
void TurnLedLightON();
void TurnLedLightOFF();
int GetLedLightBrightness();
int GetLedLightState();
#endif /* LEDLIGHTCTRL_H */
@@ -0,0 +1,284 @@
#include "LoraNetworkInterface.h"
#include "ProtocolDefs.h"
#include "NetworkProtocol.h"
#include "InternalUart.h"
#include "define.h"
#include "BoardCfg.h"
#include "Uart.h"
#include "ChaletPowerRelay.h"
#include "HarakiriRelay.h"
#include "BatteryMonitor.h"
#include "LedLightCtrl.h"
#include "TemperatureSensor.h"
#include "SPI_Flash.h"
#include "FlashMapping.h"
#include "LoraWatchdog.h"
#include "versionbuild.h"
//#include "WiFiCtrl.h"
//
//enum eWiFiState
//{
// WIFI_MODULE_OFF_STATE = 0,
// WIFI_CONNECTED_STATE,
// WIFI_DISCONNECTED_STATE,
// WIFI_INIT_ERROR_STATE,
// WIFI_UNKNOWN_STATE
//};
unsigned char mLoraPreamble[3]={0x00,LORA_MASTER_ADDRESS,LORA_CHANNEL};
static const char mFirmwareVersion[15] = VERSIONNUMBER;
unsigned int mTotalMasterNbRequests = 0;
void ExecuteMasterCommand(int Command, unsigned char *Data)
{
//Whatever was the command, we are online...
LORA_MODULE_RX_LED_PIN = LED_OFF;
KickLoraWatchdog();
// printf("EXEC\n\n");
ChaletPowerRelayKickTimer();
mTotalMasterNbRequests++;
switch(Command)
{
case CHALET_INTERFACE_ACK:
{
break;
}
case CHALET_GENERAL_STATUS_REQUEST:
{
float FloatVoltage = GetBatteryVoltage();
float FloatTemperature = TempSensorGetTemp();
unsigned int BattVoltage = *((int*)&FloatVoltage);
unsigned int Temperature = *((int*)&FloatTemperature);
int SolarPanelCurrent = GetSolarPanelCurrent();
int SOC = GetBatterySOC();
char GeneralStatus = 0;
char ChaletStatus[18];
if(GetChaletPowerRelayState() == CHALET_POWER_RELAY_ON_STATE)
{
GeneralStatus |= LORA_CHALET_STATUS_POWER_RELAY_MASK;
}
if(GetCurrentModuleOK() == true)
{
GeneralStatus |= LORA_CHALET_STATUS_CUR_SENSOR_MASK;
}
ChaletStatus[0] = GeneralStatus; //General Status
ChaletStatus[1] = GetWiFiSate(); //Wifi Module state
ChaletStatus[2] = (char)(BattVoltage & 0x000000FF); //Battery Voltage 1
BattVoltage >>= 8;
ChaletStatus[3] = (char)(BattVoltage & 0x000000FF); //Battery Voltage 2
BattVoltage >>= 8;
ChaletStatus[4] = (char)(BattVoltage & 0x000000FF); //Battery Voltage 3
BattVoltage >>= 8;
ChaletStatus[5] = (char)(BattVoltage & 0x000000FF); //Battery Voltage 4
ChaletStatus[6] = (char)(SolarPanelCurrent & 0x000000FF); //Solar panel Current 1
SolarPanelCurrent >>= 8;
ChaletStatus[7] = (char)(SolarPanelCurrent & 0x000000FF); //Solar panel Current 2
ChaletStatus[8] = (char)(SOC & 0x000000FF); //Battery SOC 1
SolarPanelCurrent >>= 8;
ChaletStatus[9] = (char)(SolarPanelCurrent & 0x000000FF); //Battery SOC 2
ChaletStatus[10] = (char)(Temperature & 0x000000FF); //Temperature 1
Temperature >>= 8;
ChaletStatus[11] = (char)(Temperature & 0x000000FF); //Temperature 2
Temperature >>= 8;
ChaletStatus[12] = (char)(Temperature & 0x000000FF); //BTemperature 3
Temperature >>= 8;
ChaletStatus[13] = (char)(Temperature & 0x000000FF); //Temperature 4
int tmp = mTotalMasterNbRequests;
ChaletStatus[14] = (char)(mTotalMasterNbRequests & 0x000000FF); //Total Nb Requests 1
mTotalMasterNbRequests >>= 8;
ChaletStatus[15] = (char)(mTotalMasterNbRequests & 0x000000FF); //Total Nb Requests 2
mTotalMasterNbRequests >>= 8;
ChaletStatus[16] = (char)(mTotalMasterNbRequests & 0x000000FF); //Total Nb Requests 3
mTotalMasterNbRequests >>= 8;
ChaletStatus[17] = (char)(mTotalMasterNbRequests & 0x000000FF); //Total Nb Requests 4
mTotalMasterNbRequests = tmp;
SendLoraNetworkCommand(CHALET_GENERAL_STATUS_RESPONSE,ChaletStatus,18);
HEARTBEAT_LED_1_PIN = ~HEARTBEAT_LED_1_PIN;
break;
}
case CHALET_AC_POWER_STATE_STATUS_REQUEST:
{
char PowerStatus = GetChaletPowerRelayState();
SendLoraNetworkCommand(CHALET_AC_POWER_STATE_STATUS_RESPONSE,&PowerStatus,1);
break;
}
case CHALET_AC_POWER_SET_STATE_REQUEST:
{
char response = CHALET_POWER_RELAY_UNKNOWN_STATE;
if(Data[0] == CHALET_POWER_RELAY_OFF_STATE)
{
ChaletPowerRelayTurnOff();
response = CHALET_POWER_RELAY_OFF_STATE;
}
else if(Data[0] == CHALET_POWER_RELAY_ON_STATE)
{
ChaletPowerRelayTurnOn();
response = CHALET_POWER_RELAY_ON_STATE;
}
else
{
//invalid state requested.... don't do anything
response = CHALET_POWER_RELAY_UNKNOWN_STATE;
}
SendLoraNetworkCommand(CHALET_AC_POWER_SET_STATE_RESPONSE,&response,1);
break;
}
case CHALET_BATTERY_VOLTAGE_REQUEST:
{
break;
}
case CHALET_WIFI_STATUS_REQUEST:
{
break;
}
case CHALET_WIFI_SET_STATE_REQUEST:
{
char response = WIFI_UNKNOWN_STATE;
if(Data[0] == 0)
{
TurnOFFWiFi();
response = 0;
}
else if(Data[0] == 1)
{
if(GetWiFiSate() != WIFI_CONNECTED_STATE)
{
InitWiFi();
response = GetWiFiSate();
}
else
{
response = 1;
}
}
else
{
//invalid state requested.... don't do anything
response = WIFI_UNKNOWN_STATE;
}
SendLoraNetworkCommand(CHALET_WIFI_SET_STATE_RESPONSE,&response,1);
break;
}
case CHALET_DO_HARAKIRI_REQUEST:
{
char response;
if(Data[0] == 0xBA &&
Data[1] == 0xAD &&
Data[2] == 0xBE &&
Data[3] == 0xEF)
{
//Magic word is OK... let's suicide...
response = 0x01;
//First, send an ACK to master (this is blocking so it's OK)
SendLoraNetworkCommand(CHALET_DO_HARAKIRI_CONFIRMATION,&response,1);
HarakiriRelayTurnOff();
}
else
{
response = 0x00;
SendLoraNetworkCommand(CHALET_DO_HARAKIRI_CONFIRMATION,&response,1);
}
break;
}
case CHALET_REBOOT_CPU_REQUEST:
{
char response;
if(Data[0] == 0xBA &&
Data[1] == 0xAD &&
Data[2] == 0xCA &&
Data[3] == 0xFE)
{
//Magic word is OK... let's reboot...
response = 0x01;
//First, send an ACK to master (this is blocking so it's OK)
SendLoraNetworkCommandBlocking(CHALET_REBOOT_CPU_RESPONSE,&response,1);
Sleep(100);
TurnOFFWiFi();
Sleep(100);
SoftReset();
}
else
{
response = 0x00;
SendLoraNetworkCommand(CHALET_DO_HARAKIRI_CONFIRMATION,&response,1);
}
break;
}
case CHALET_GET_STORED_WIFI_SETTINGS_REQUEST:
{
char response[8];
SPIFlashReadBuffer(response,8,FLASH_WIFI_IP_ADDRESS);
SendLoraNetworkCommand(CHALET_GET_STORED_WIFI_SETTINGS_RESPONSE,response,8);
break;
}
case CHALET_SET_STORED_WIFI_SETTINGS_REQUEST:
{
char response = 0;
if(SPIFlashWriteBuffer(Data,8,FLASH_WIFI_IP_ADDRESS) == 1)
{
response = 1;
}
SendLoraNetworkCommand(CHALET_SET_STORED_WIFI_SETTINGS_RESPONSE,&response,1);
break;
}
case CHALET_GET_FIRMWARE_VERSION_REQUEST:
{
SendLoraNetworkCommand(CHALET_GET_FIRMWARE_VERSION_RESPONSE,(unsigned char*)mFirmwareVersion,15);
break;
}
case CHALET_CLEAR_COMMS_STATISTICS_REQUEST:
{
char response = 1;
mTotalMasterNbRequests = 0;
SendLoraNetworkCommand(CHALET_CLEAR_COMMS_STATISTICS_RESPONSE,&response,1);
break;
}
}
}
void SendLoraNetworkCommand(int Command, unsigned char *Data, unsigned int DataSize)
{
unsigned char *Payload;
unsigned int PayloadSize;
//unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags, int *FrameSize)
Payload = ProtocolGetFrame(ID_MASTER,MASTER_ADDRESS,ID_CHALET_DEVICE,Command,Data,DataSize,0,&PayloadSize);
UartTransmitData(NETWORK_UART_PORT,mLoraPreamble,3);
UartTransmitData(NETWORK_UART_PORT,Payload,PayloadSize);
}
void SendLoraNetworkCommandBlocking(int Command, unsigned char *Data, unsigned int DataSize)
{
unsigned char *Payload;
unsigned int PayloadSize;
//unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags, int *FrameSize)
Payload = ProtocolGetFrame(ID_MASTER,MASTER_ADDRESS,ID_CHALET_DEVICE,Command,Data,DataSize,0,&PayloadSize);
SendInternalUartDataBlocking(mLoraPreamble,3,NETWORK_UART_PORT);
SendInternalUartDataBlocking(Payload,PayloadSize,NETWORK_UART_PORT);
}
void TestTx()
{
char toto = 0x03;
SendInternalUartDataBlocking(mLoraPreamble,3,NETWORK_UART_PORT);
}
@@ -0,0 +1,17 @@
#ifndef LORANEETWORKINTERFACE_H /* Guard against multiple inclusion */
#define LORANEETWORKINTERFACE_H
#define LORA_CHANNEL 0x04
#define LORA_MASTER_ADDRESS 0x05
#define LORA_CHALET_STATUS_POWER_RELAY_MASK 0x01
#define LORA_CHALET_STATUS_CUR_SENSOR_MASK 0x02
void ExecuteMasterCommand(int Command, unsigned char *Data);
void SendLoraNetworkCommand(int Command, unsigned char *Data, unsigned int DataSize);
void SendLoraNetworkCommandBlocking(int Command, unsigned char *Data, unsigned int DataSize); //USE WITH CARE
void TestTx();
#endif /* LORANEETWORKINTERFACE_H */
+101
View File
@@ -0,0 +1,101 @@
//#include <proc/p32mx440f256h.h>
#include "HarakiriRelay.h"
#include "BoardCfg.h"
#include "timer.h"
#include "LoraWatchdog.h"
int mLoraSMState;
void InitLoraWatchdog()
{
mLoraSMState = LORA_WATCHDOG_OK_STATE;
TimerStart(LORA_WATCHDOG_TIMER,LORA_WATCHDOG_MODULE_RESET_TIMEOUT);
}
void TickLoraWatchdog()
{
LoraWatchdogStateMachine(LORA_SM_TICK_EVENT);
}
void LoraWatchdogStateMachine(int Event)
{
switch(mLoraSMState)
{
case LORA_WATCHDOG_OK_STATE:
{
switch(Event)
{
case LORA_SM_TICK_EVENT:
{
if(IsTimerExpired(LORA_WATCHDOG_TIMER))
{
//We lost the comm... reset the LoRa module
LORA_MODULE_RELAY_PIN = 1; //Turn OFF the LoRa module
TimerStart(LORA_WATCHDOG_TIMER,LORA_WATCHDOG_MODULE_OFF_TIMEOUT);
mLoraSMState = LORA_WATCHDOG_RESET_LORA_MODULE_STATE;
}
break;
}
case LORA_SM_KICK_EVENT:
{
//All is well...
TimerStart(LORA_WATCHDOG_TIMER,LORA_WATCHDOG_MODULE_RESET_TIMEOUT);
break;
}
}
break;
}
case LORA_WATCHDOG_RESET_LORA_MODULE_STATE:
{
switch(Event)
{
case LORA_SM_TICK_EVENT:
case LORA_SM_KICK_EVENT://That would be very weird since the LoRa module is OFF!!!
{
if(IsTimerExpired(LORA_WATCHDOG_TIMER))
{
//Reset is done, turn module back ON.
LORA_MODULE_RELAY_PIN = 0; //Turn ON the LoRa module
TimerStart(LORA_WATCHDOG_TIMER,LORA_WATCHDOG_REBOOT_TIMEOUT); //If we don't get Comm. back after this delay... reboot the PIC
mLoraSMState = LORA_WATCHDOG_WAIT_FOR_RECONNECT_STATE;
}
break;
}
}
break;
}
case LORA_WATCHDOG_WAIT_FOR_RECONNECT_STATE:
{
switch(Event)
{
case LORA_SM_TICK_EVENT:
{
if(IsTimerExpired(LORA_WATCHDOG_TIMER))
{
TurnOFFWiFi();
Sleep(100);
SoftReset();
}
break;
}
case LORA_SM_KICK_EVENT:
{
//Communication is re-established.
TimerStart(LORA_WATCHDOG_TIMER,LORA_WATCHDOG_MODULE_RESET_TIMEOUT);
mLoraSMState = LORA_WATCHDOG_OK_STATE;
break;
}
}
break;
}
}
}
void KickLoraWatchdog()
{
LoraWatchdogStateMachine(LORA_SM_KICK_EVENT);
}
+38
View File
@@ -0,0 +1,38 @@
/*
* File: LoraWatchdog.h
* Author: JF
*
*
*/
#ifndef LORAWATCHDOG_H
#define LORAWATCHDOG_H
#include "define.h"
#define LORA_WATCHDOG_MODULE_RESET_TIMEOUT 3600000 //1h Time without comm. before we reset the LoRa module
#define LORA_WATCHDOG_REBOOT_TIMEOUT 1200000 //20 minutes Time to reboot after we reset the LoRa module
#define LORA_WATCHDOG_MODULE_OFF_TIMEOUT 4000 //Keep the LoRa module off for 2 seconds when reseting it.
enum eLoraWDSMStates
{
LORA_WATCHDOG_OK_STATE,
LORA_WATCHDOG_RESET_LORA_MODULE_STATE,
LORA_WATCHDOG_WAIT_FOR_RECONNECT_STATE
};
enum eLoraWDEvents
{
LORA_SM_TICK_EVENT,
LORA_SM_KICK_EVENT
};
void InitLoraWatchdog();
void TickLoraWatchdog();
void LoraWatchdogStateMachine(int Event);
void KickLoraWatchdog();
#endif /* HARAKIRIRELAY_H */
+282
View File
@@ -0,0 +1,282 @@
#include "define.h"
#include "MasterCtrlInterface.h"
#ifdef USE_WINC1500
#else
#include "TCPIP_Stack/TCPIP.h"
#endif
#include "NetworkProtocol.h"
#include "ProtocolDefs.h"
#include "timer.h"
#include <stdio.h>
#include "ValveCtrl.h"
#include "FlowMeter.h"
#ifdef USE_WINC1500
#else
TCP_SOCKET MySocket;
static BYTE MasterIP[] = "192.168.0.100";
DWORD MasterPort = 2182;
#endif
int mConnectionState = MASTER_STATE_DISCONNECTED;
int InitMasterCtrlIF()
{
ProtocolInit();
TimerStart(MASTER_CONNECTION_TIMER,MASTER_RECONNECTION_TIMEOUT);
return 1;
}
int ConnectToMasterCtrl()
{
#ifdef USE_WINC1500
#else
MySocket = TCPOpen((DWORD) (PTR_BASE) & MasterIP[0], TCP_OPEN_RAM_HOST, MasterPort, TCP_PURPOSE_GENERIC_TCP_CLIENT);
// Abort operation if no TCP socket of type TCP_PURPOSE_GENERIC_TCP_CLIENT is available
// If this ever happens, you need to go add one to TCPIPConfig.h
if (MySocket == INVALID_SOCKET)
{
printf("Could not open socket to MasterCtrl\n");
return 0;
}
printf("MasterCtrl Socket opened\n");
#endif
return 1;
}
void TickMasterCtrlInterface()
{
#ifdef USE_WINC1500
#else
WORD Pending = TCPIsGetReady(MySocket);
if (Pending != 0)
{
// printf("Rx %d bytes\n",Pending);
int i = 0;
for(i = 0; i < Pending; i++)
{
BYTE Byte;
if(TCPGet(MySocket,&Byte) == TRUE)
{
ProtocolAnalyzeNewData(Byte);
}
}
}
#ifdef CONNECT_DEVICE_TO_NETWORK
if(mConnectionState == MASTER_STATE_DISCONNECTED)
{
if(IsTimerExpired(MASTER_CONNECTION_TIMER))
{
TimerStart(MASTER_CONNECTION_TIMER,MASTER_RESPONSE_TIMEOUT);
mConnectionState = MASTER_STATE_CONNECTING;
ConnectToMasterCtrl();
}
}
else if(mConnectionState == MASTER_STATE_CONNECTING)
{
// if(IsTimerExpired(MASTER_CONNECTION_TIMER) == true) //
// {
// TCPClose(MySocket);
// TimerStart(MASTER_CONNECTION_TIMER,MASTER_RESPONSE_TIMEOUT);
// ConnectToMasterCtrl();
// }
}
else if(mConnectionState == MASTER_STATE_CONNECTED)
{
// if(IsTimerExpired(MASTER_CONNECTION_TIMER))
{
if(TCPIsConnected(MySocket) == FALSE)
{
//we got disconnected...
mConnectionState = MASTER_STATE_DISCONNECTED;
TCPClose(MySocket);
printf("Connection with MasterCtrl lost..\n");
}
TimerStart(MASTER_CONNECTION_TIMER,MASTER_RECONNECTION_TIMEOUT);
}
}
#endif
#endif
}
void NewMasterMessageReceived(char* Message)
{
// char Sender = Message[FRAME_SENDER_DEVICE_ID_INDEX];
char Target = Message[FRAME_DEST_DEVICE_ID_INDEX];
unsigned char Command = Message[FRAME_COMMAND_INDEX];
char *Data = &Message[FRAME_DATA_INDEX];
// printf("MasterMsgReceived %d \n",Command);
if(Target == ID_ETHERNET_VIRTUAL)
{
switch(Command)
{
case ETH_NETWK_DEVICE_INFO_REQUEST:
{
char Data[2];
Data[0] = ID_SPRINKLER_DEVICE;
Data[1] = MY_DEVICE_ADDRESS; //Address
SendFrame(ID_MASTER,MASTER_ADDRESS,ID_ETHERNET_VIRTUAL, ETH_NETWK_DEVICE_INFO_RESPONSE, Data,2,0);
printf("Rx Device info request\n");
// int FrameSize = -1;
// unsigned char *FramePtr = ProtocolGetFrame(ID_MASTER,MASTER_ADDRESS,ID_ETHERNET_VIRTUAL, ETH_NETWK_DEVICE_INFO_RESPONSE, Data,2,0, &FrameSize);
//
// if(FrameSize > 0)
// {
// TCPPutArray(MySocket,FramePtr,FrameSize);
// }
break;
}
case ETH_NETWK_CONNECTION_REFUSED:
{
printf("Connection to server refused\n");
break;
}
case ETH_NETWK_SET_DEVICE_INFO_ACK:
{
//Connected!
mConnectionState = MASTER_STATE_CONNECTED;
TimerStart(MASTER_CONNECTION_TIMER,MASTER_RECONNECTION_TIMEOUT);
printf("Connected to server\n");
break;
}
case ETH_NETWK_DEVICE_INFO_RESPONSE:
default:
{
//error...
break;
}
}
}
else if(Target == ID_SPRINKLER_DEVICE)
{
switch(Command)
{
case SPRINKLER_DEVICE_ACK:
{
break;
}
case SPRINKLER_DEVICE_STATUS_REQUEST:
{
unsigned char data[6];
data[0] = (unsigned char)GetValveState();
GetCurrentFlowBytes(&data[1]);
data[3] = 0;
data[4] = 0;
data[5] = 0;
SendFrame(ID_MASTER,MASTER_ADDRESS,ID_SPRINKLER_DEVICE, SPRINKLER_DEVICE_STATUS_RESPONSE, data,6,0);
// printf("Status sent\n");
break;
}
case SPRINKLER_DEVICE_SET_SPRINKLER_STATE_REQUEST:
{
unsigned char *MsgData;
char data;
MsgData = ProtocolMsgDataPtr();
if(*MsgData == 1)
{
SetValve(VALVE_ON);
data = 1;
}
else if(*MsgData == 1)
{
SetValve(VALVE_OFF);
data = 1;
}
else
{
data = 0;
}
SendFrame(ID_MASTER,MASTER_ADDRESS,ID_SPRINKLER_DEVICE, SPRINKLER_DEVICE_SET_SPRINKLER_STATE_ACK,&data,1,0);
break;
}
case SPRINKLER_DEVICE_GET_SPRINKLER_STATE_REQUEST:
{
unsigned char data;
data = (unsigned char)GetValveState();
SendFrame(ID_MASTER,MASTER_ADDRESS,ID_SPRINKLER_DEVICE, SPRINKLER_DEVICE_GET_SPRINKLER_STATE_RESPONSE,&data,1,0);
break;
}
case SPRINKLER_DEVICE_GET_WATER_FLOW_REQUEST:
{
unsigned char data[2];
GetCurrentFlowBytes(data);
SendFrame(ID_MASTER,MASTER_ADDRESS,ID_SPRINKLER_DEVICE, SPRINKLER_DEVICE_GET_WATER_FLOW_RESPONSE,data,2,0);
break;
}
case SPRINKLER_DEVICE_GET_MOISTURE_REQUEST:
{
break;
}
case SPRINKLER_DEVICE_SET_PROGRAM_REQUEST:
{
break;
}
case SPRINKLER_DEVICE_GET_PROGRAM_REQUEST:
{
break;
}
case SPRINKLER_DEVICE_SET_PARAMETERS_REQUEST:
{
break;
}
case SPRINKLER_DEVICE_GET_PARAMETERS_REQUEST:
{
break;
}
case SPRINKLER_DEVICE_STATUS_RESPONSE:
case SPRINKLER_DEVICE_SET_SPRINKLER_STATE_ACK:
case SPRINKLER_DEVICE_GET_SPRINKLER_STATE_RESPONSE:
case SPRINKLER_DEVICE_GET_WATER_FLOW_RESPONSE:
case SPRINKLER_DEVICE_GET_MOISTURE_RESPONSE:
case SPRINKLER_DEVICE_SET_PROGRAM_ACK:
case SPRINKLER_DEVICE_GET_PROGRAM_RESPONSE:
case SPRINKLER_DEVICE_SET_PARAMETERS_ACK:
case SPRINKLER_DEVICE_GET_PARAMETERS_RESPONSE:
default:
{
//error
break;
}
}
}
else
{
//Ignore..???
}
}
bool SendFrame(unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags)
{
int FrameSize = -1;
unsigned char *FramePtr = ProtocolGetFrame(DestDevice,DestAddress,SenderDevice, Cmd, Data,Size,Flags,&FrameSize);
if(FrameSize > 0)
{
#ifdef USE_WINC1500
#else
TCPPutArray(MySocket,FramePtr,FrameSize);
#endif
}
else
{
return false;
}
return true;
}
@@ -0,0 +1,27 @@
/*
* File: MasterCtrlInterface.h
* Author: JF
*
* Created on March 31, 2017, 2:41 PM
*/
#ifndef MASTERCTRLINTERFACE_H
#define MASTERCTRLINTERFACE_H
enum eMasterConnectionStates
{
MASTER_STATE_DISCONNECTED,
MASTER_STATE_CONNECTING,
MASTER_STATE_CONNECTED
};
int InitMasterCtrlIF(void);
int ConnectToMasterCtrl(void);
void TickMasterCtrlInterface(void);
void MasterCtrlSM(int Event);
void NewMasterMessageReceived(char* Message);
bool SendFrame(unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags);
#endif /* MASTERCTRLINTERFACE_H */
+324
View File
@@ -0,0 +1,324 @@
/**********************************************************************
Project: Automatic cat feeder
Date: march 19 2006
Author: Jean-Fran�ois Martel
Target: PIC 18F252
Compiler: Microchip mcc18
Filename: Protocol.c
File description: Communication protocol implementation.
jean-francois.martel@polymtl.ca
**********************************************************************/
#include "define.h"
#include "NetworkProtocol.h"
#include "Uart.h"
#include <string.h>
#include "ProtocolDefs.h"
#include "MasterCtrlInterface.h"
#include "LoraNetworkInterface.h"
unsigned char mRxData[MAX_MESSAGE_SIZE+10], mTxData[MAX_MESSAGE_SIZE+10];
unsigned int DataSize = 0;
unsigned int DataCtr = 0;
unsigned int BufPtr = 0;
unsigned char RxPtr = 0;
unsigned char Command = 0;
unsigned char State = RxHeader;
unsigned char CRC = 0;
unsigned char SenderID = 0;
unsigned char SenderAddress = 0;
unsigned char Flags = 0;
unsigned char IsUpdating = 0;
unsigned char *BmpDataPtr = 0;
static char MyDeviceID = ID_SPRINKLER_DEVICE;
void ProtocolInit(void)
{
ResetStateMachine();
}
void StateMachine(unsigned char Data)
{
switch(State)
{
case Initialization: //Reset all pointers and data...
{
DataSize = 0;
BufPtr = 0;
RxPtr = 0;
Command = 0;
CRC = 0;
State = RxHeader;
break;
}
case RxHeader: //Wait for data header...
{
if(Data == FRAME_HEADER)
{
mRxData[BufPtr++] = Data;
State = RxAdd;
CRC ^= Data;
}
else
{
DataSize = 0;
ResetStateMachine();
}
break;
}
case RxAdd: //Sender Address.
{
SenderAddress = Data;
mRxData[BufPtr++] = Data;
State = RxID;
CRC ^= Data;
break;
}
case RxID: //Sender ID
{
mRxData[BufPtr++] = Data;
State = RxMyID;
SenderID = Data;
CRC ^= Data;
break;
}
case RxMyID:
{
// if(Data != MyDeviceID && Data != BROADCAST_VALUE) //Message is not for this type of device and it's not a broadcast
// {
// ResetStateMachine();
// break;
// }
mRxData[BufPtr++] = Data;
State = RxMyAddress;
CRC ^= Data;
break;
}
case RxMyAddress:
{
if(Data != MY_DEVICE_ADDRESS && Data != BROADCAST_VALUE) //Message is not for this device address and it's not a broadcast
{
ResetStateMachine();
break;
}
mRxData[BufPtr++] = Data;
State = RxFlags;
CRC ^= Data;
break;
}
case RxFlags:
{
Flags = Data;
mRxData[BufPtr++] = Data;
State = RxCMD;
CRC ^= Data;
break;
}
case RxCMD:
{
Command = Data;
mRxData[BufPtr++] = Data;
State = RxSize1;
CRC ^= Data;
break;
}
case RxSize1: //Data size MSB
{
DataSize = 0;
DataSize = (unsigned int)Data;
DataSize <<= 8;
mRxData[BufPtr++] = Data;
State = RxSize2;
CRC ^= Data;
break;
}
case RxSize2: //Data size
{
DataSize |= (unsigned int)Data;
DataSize <<= 8;
mRxData[BufPtr++] = Data;
State = RxSize3;
CRC ^= Data;
break;
}
case RxSize3: //Data size
{
DataSize |= (unsigned int)Data;
DataSize <<= 8;
mRxData[BufPtr++] = Data;
State = RxSize4;
CRC ^= Data;
break;
}
case RxSize4: //Data size LSB
{
DataSize |= (unsigned int)Data;
mRxData[BufPtr++] = Data;
if(DataSize > MAX_MESSAGE_SIZE)
ResetStateMachine();
if(DataSize == 0)
State = RxCRC;
else
State = RxData;
CRC ^= Data;
break;
}
case RxData:
{
CRC ^= Data;
mRxData[BufPtr++] = Data;
DataCtr++;
if(DataCtr == DataSize)
{
State = RxCRC;
}
break;
}
case RxCRC:
{
if(Data != CRC)
{
ResetStateMachine();
// ProtocolAcknowledge(0,Command,0);
break;
}
// NewMasterMessageReceived(mRxData);
ExecuteMasterCommand(Command,ProtocolMsgDataPtr());
ResetStateMachine();
break;
}
default:
{
ResetStateMachine();
break;
}
}
}
void ProtocolAnalyzeNewData(unsigned char Data)
{
// mRxData[RxPtr] = Data;
// printf("%X",Data);
StateMachine(Data);
}
void ResetStateMachine(void)
{
DataSize = 0;
BufPtr = 0;
RxPtr = 0;
Command = 0;
CRC = 0;
State = RxHeader;
DataCtr = 0;
Flags = 0;
SenderAddress = 0;
}
void ProtocolExecCmd(void)
{
switch(Command)
{
case RX_GET_STATUS:
{
unsigned char StatusByte =0;
// memcpy(&StatusByte, &IRRemoteStatus, sizeof(IRRemoteStatus));
// ProtocolSendCmd(TX_DEADBOLT_STATUS,&StatusByte,sizeof(StatusByte),1,0);
break;
}
}
}
void ProtocolAcknowledge(unsigned char Answer,unsigned char Cmd, unsigned char Data)
{
unsigned char data[2];
if(Answer == 1)
{
data[0] = PROTOCOL_ACK; //CMD
}
else
{
data[0] = PROTOCOL_NAK; //CMD
}
data[1] = Cmd;
// ProtocolSendCmd(TX_NETWORK_ACK,&data[0],2,1,0);
}
unsigned char ProtocolCalcCrc(unsigned char* Buffer,unsigned char size)
{
unsigned char CRC = 0;
unsigned char i;
for(i = 0; i < size; i++)
CRC ^= Buffer[i];
return CRC;
}
unsigned char ProtocolIsReceiving(void)
{
if(State == RxHeader)
return 0; // Idle...
else
return 1; //receiving from serial port
}
unsigned char* ProtocolGetFrame(unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags, int *FrameSize)
{
if(Size > MAX_MESSAGE_SIZE)
{
*FrameSize = 0;
return &mTxData[FRAME_HEADER_INDEX];
}
mTxData[FRAME_HEADER_INDEX] = FRAME_HEADER; //header
mTxData[FRAME_SENDER_ADDRESS_INDEX] = MY_DEVICE_ADDRESS; //My Address
mTxData[FRAME_SENDER_DEVICE_ID_INDEX] = SenderDevice; //My ID
mTxData[FRAME_DEST_DEVICE_ID_INDEX] = DestDevice; //Destination ID
mTxData[FRAME_DEST_ADDRESS_INDEX] = DestAddress ;//Address; //Destination Address
mTxData[FRAME_FLAGS_INDEX] = Flags; //Flags
mTxData[FRAME_COMMAND_INDEX] = Cmd; //Command to send
mTxData[FRAME_SIZE1_INDEX] = (unsigned char)((Size >> 24) & 0xFF);
mTxData[FRAME_SIZE2_INDEX] = (unsigned char)((Size >> 16) & 0xFF);
mTxData[FRAME_SIZE3_INDEX] = (unsigned char)((Size >> 8) & 0xFF);
mTxData[FRAME_SIZE4_INDEX] = (unsigned char)(Size & 0xFF);
memcpy((void*)&mTxData[FRAME_DATA_INDEX],(void*)Data,Size); //Cmd data
mTxData[Size+FRAME_DATA_INDEX] = ProtocolCalcCrc(mTxData,Size + FRAME_DATA_INDEX); // CRC
*FrameSize = Size + FRAME_INDEX_NBR;
return &mTxData[FRAME_HEADER_INDEX];
}
unsigned char *ProtocolMsgDataPtr()
{
return &mRxData[FRAME_DATA_INDEX];
}
+77
View File
@@ -0,0 +1,77 @@
/**********************************************************************
Project: Automatic cat feeder
Date: march 19 2006
Author: Jean-Fran�ois Martel
Target: PIC 18F252
Compiler: Microchip mcc18
Filename: Protocol.h
File description: Communication protocol implementation.
jean-francois.martel@polymtl.ca
**********************************************************************/
#ifndef BOOTLOADERINTERFACE_H
#define BOOTLOADERINTERFACE_H
//Protocol buffer specific definitions
#define MASTER_ADDRESS 0x01
#define MY_DEVICE_ADDRESS 0x01
#define ADDRESS 0x01
//State Machine states
enum States
{
Initialization,
RxHeader,
RxAdd,
RxID,
RxMyID,
RxMyAddress,
RxFlags,
RxCMD,
RxSize1,
RxSize2,
RxSize3,
RxSize4,
RxData,
RxCRC
};
//enum DEVICES_IDS
//{
// ID_MASTER, //Master Controller
// ID_CONSOLE, //LCD Console
// ID_PC, //PC
// ID_AV_MUX, //Audio Video Multiplexer
// ID_IR_REMOTE,
// ID_DEADBOLT
//};
//enum MESSAGE_IDS
//{
// TX_NETWORK_ACK = 1,
// RX_GET_STATUS,
// TX_DEADBOLT_STATUS,
//
// MAX_NETWORK_CMD
//};
//State machine states definition
void ProtocolInit(void);
void StateMachine(unsigned char STATE);
void ProtocolAnalyzeNewData(unsigned char RxByte);
void ResetStateMachine(void);
void ProtocolExecCmd(void);
void ProtocolAcknowledge(unsigned char Answer,unsigned char Cmd, unsigned char Data);
unsigned char* ProtocolGetFrame(unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags, int *FrameSize);
unsigned char ProtocolCalcCrc(unsigned char* Buffer,unsigned char size);
unsigned char ProtocolIsReceiving(void);
unsigned char *ProtocolMsgDataPtr();
#endif
+31
View File
@@ -0,0 +1,31 @@
#include "PWMCtrl.h"
#include "BoardCfg.h"
void PWMSetValue(unsigned int percent)
{
if(percent > 100)
percent = 100;
#ifdef REVERSE_POLARITY
percent = 100 - percent;
#endif
LED_PWM_VAL_REG = ((PWM_RANGE_MAX / 100) * percent);
}
void PWMShutDown()
{
PWMSetValue(0);
}
void PWMSetAbsoluteValue(unsigned int value)
{
if(value > PWM_RANGE_MAX)
{
value = PWM_RANGE_MAX;
}
LED_PWM_VAL_REG = value;
}
+18
View File
@@ -0,0 +1,18 @@
/*
* File: PWMCtrl.h
* Author: JF
*
* Created on November 29, 2018, 5:24 PM
*/
#ifndef PWMCTRL_H
#define PWMCTRL_H
#define REVERSE_POLARITY
void PWMSetValue(unsigned int percent);
void PWMShutDown();
void PWMSetAbsoluteValue(unsigned int value);
#endif /* PWMCTRL_H */
+97
View File
@@ -0,0 +1,97 @@
#include "BoardCfg.h"
int InitBoard()
{
HEARTBEAT_LED_1_PIN_DIR = PIN_OUTPUT;
// HEARTBEAT_LED_2_PIN_DIR = PIN_OUTPUT;
// HEARTBEAT_LED_2_PIN = LED_ON;
HEARTBEAT_LED_1_PIN = LED_ON;
GP_DEBUG_1_PIN_DIR = PIN_OUTPUT;
GP_DEBUG_1_PIN = 0;
GP_DEBUG_2_PIN_DIR = PIN_OUTPUT;
GP_DEBUG_2_PIN = 0;
SPI_SDI_PIN_DIR = PIN_INPUT;
SD_SPI_SS_PIN_DIR = PIN_OUTPUT;
SPI_SDO_PIN_DIR = PIN_OUTPUT;
SPI_SCK_PIN_DIR = PIN_OUTPUT;
//Wifi (WINC1500 module)
WIFI_SPI_SS_PIN_DIR = PIN_OUTPUT;
WIFI_SPI_SS_PIN = 1;
WIFI_IRQ_PIN_DIR = PIN_INPUT;
// WIFI_WAKE_PIN_DIR = PIN_OUTPUT;
// WIFI_WAKE_PIN = 1;
WIFI_SPI_CFG_PIN_DIR = PIN_OUTPUT;
WIFI_SPI_CFG_PIN = 0;
WIFI_CHP_EN_PIN_DIR = PIN_OUTPUT;
WIFI_CHP_EN_PIN = 0;
WIFI_CHP_RST_PIN_DIR = PIN_OUTPUT;
WIFI_CHP_RST_PIN = 0;
//Wifi chip IRQ
IEC0bits.INT0IE = 0;
IFS0bits.INT0IF = 0;
INTCONbits.INT0EP = 0; //Rising edge
IPC0bits.INT0IP = 3;
IPC0bits.INT0IS = 0;
IEC0bits.INT0IE = 1;
//Wifi chip SPI
SPI2CON = 0;
SPI2CONbits.MSTEN = 1;
SPI2CONbits.CKE = 0;
SPI2CONbits.SMP = 0;
SPI2CONbits.CKP = 0;
SPI2BRG = SPICalculateBRG(PERIPHERAL_FREQ, 500000);
SPI2CONbits.ON = 1;
//Control knob encoder
KNOB_PH_A_PIN_DIR = PIN_INPUT;
KNOB_PH_B_PIN_DIR = PIN_INPUT;
KNOB_TGLE_BTN_PIN_DIR = PIN_INPUT;
IEC0bits.INT1IE = 0;
IFS0bits.INT1IF = 0;
INTCONbits.INT1EP = 1; //Rising edge
IPC1bits.INT1IP = 2;
IPC1bits.INT1IS = 1;
// IEC0bits.INT1IE = 1;
//Led controller PWM
LED_PWM_PIN_DIR = PIN_OUTPUT;
LED_PWM_PIN = 0;
OC3CON = 0;
OC3R = 0;
OC3RS = 2000; //50% PWM
OC3CONbits.OCTSEL = 0;
OC3CONbits.OCM = 0b110; //PWM mode, no fault protection
T2CONbits.TON = 0; // Disable Timer
T2CONbits.TCS = 0; // Select internal instruction cycle clock
T2CONbits.TGATE = 0; // Disable Gated Timer mode
T2CONbits.TCKPS = 0b00; // Select 1:1 Prescaler
TMR2 = 0x00; // Clear timer register
//PR2 = 256; // Load the period value
PR2 = PWM_RANGE_MAX; //10KHz @ 80MHz
IPC2bits.T2IP = 0x01; // Set Timer 2 Interrupt Priority Level
IFS0bits.T2IF = 0; // Clear Timer 2 Interrupt Flag
IEC0bits.T2IE = 0; // Disable Timer 2 interrupt
T2CONbits.TON = 1; // Start Timer
OC3CONbits.ON = 1;
return RET_OK;
}
+104
View File
@@ -0,0 +1,104 @@
#include "define.h"
#include "PrintfServer.h"
#ifdef USE_WINC1500
#else
#include "TCPIP_Stack/TCPIP.h"
#endif
#include <stdio.h>
//BYTE vTelnetSession;
WORD w, w2;
#ifdef USE_WINC1500
#else
TCP_SOCKET MyPrintfSocket;
#endif
char mPrintfString[1024]; //Make shure this string is at least as big as the heap
BOOL mPrintfAvailable;
int OpenPrintfServer()
{
memset(mPrintfString,'\0',1024);
#ifdef USE_WINC1500
return 0;
#else
MyPrintfSocket = TCPOpen(0, TCP_OPEN_SERVER, 6463, TCP_PURPOSE_GENERIC_TCP_SERVER);
if (MyPrintfSocket == INVALID_SOCKET)
{
return 0;
}
mPrintfAvailable = FALSE;
return 1;
#endif
}
void TickPrintfServer()
{
int length;
static int PrintfServerTickState = PRINTF_SERVER_INIT_STATE;
switch(PrintfServerTickState)
{
case PRINTF_SERVER_INIT_STATE:
{
if(OpenPrintfServer() == 1)
{
PrintfServerTickState = PRINTF_SERVER_RUN_STATE;
}
break;
}
case PRINTF_SERVER_RUN_STATE:
{
#ifdef USE_WINC1500
#else
if(TCPIsConnected(MyPrintfSocket) == FALSE)
{
mPrintfAvailable = FALSE;
return;
}
else
{
if(mPrintfAvailable == FALSE)
{
mPrintfAvailable = TRUE;
TCPPutString(MyPrintfSocket,"Sprinkler printf console\n");
}
}
length = (int)strlen(mPrintfString);
if(length > 0 /*&& TCPIsPutReady(MySocket) > length*/)
{
TCPPutString(MyPrintfSocket,mPrintfString);
memset(mPrintfString,'\0',1024);
}
#endif
break;
}
}
}
void TelnetPutPrintf(char c)
{
if(mPrintfAvailable == FALSE)
return;
// if(strlen(mPrintfString) >= 1000)
// return;
//
// strncat(mPrintfString,&c,1);
#ifdef USE_WINC1500
#else
TCPPut(MyPrintfSocket,c);
#endif
// TCPFlush(MyPrintfSocket);
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef PRINTFSERVER_H
#define PRINTFSERVER_H
enum ePrintfServerTickStates
{
PRINTF_SERVER_INIT_STATE,
PRINTF_SERVER_RUN_STATE
};
int OpenPrintfServer();
void TickPrintfServer();
void TelnetPutPrintf(char c);
#endif
+339
View File
@@ -0,0 +1,339 @@
/**********************************************************************
Project: Automatic cat feeder
Date: march 19 2006
Author: Jean-François Martel
Target: PIC 18F252
Compiler: Microchip mcc18
Filename: Protocol.h
File description: Communication protocol implementation.
jean-francois.martel@polymtl.ca
**********************************************************************/
#ifndef PROTOCOLDEFS_H
#define PROTOCOLDEFS_H
//Protocol buffer specific definitions
#define MAX_BOOTLOADER_MESSAGE_SIZE 25
#define MAX_MESSAGE_SIZE 300
#define BOOTLOADER_MAX_MESSAGE_SIZE 50
#define FRAME_HEADER 0x8A
#define BOOTLOADER_HEADER 0xA8
#define DATA_START 11
#define PROTOCOL_ACK 0xA3
#define PROTOCOL_NAK 0x90
#define BROADCAST_VALUE 0xFF
#define MASTER_RECONNECTION_TIMEOUT 25000 //Try to reconnect every 5s
#define MASTER_RESPONSE_TIMEOUT 30000 //Wait max 30s for the master to respond...
enum eFrameIndex
{
FRAME_HEADER_INDEX = 0,
FRAME_SENDER_ADDRESS_INDEX,
FRAME_SENDER_DEVICE_ID_INDEX,
FRAME_DEST_DEVICE_ID_INDEX,
FRAME_DEST_ADDRESS_INDEX,
FRAME_FLAGS_INDEX,
FRAME_COMMAND_INDEX,
FRAME_SIZE1_INDEX,
FRAME_SIZE2_INDEX,
FRAME_SIZE3_INDEX,
FRAME_SIZE4_INDEX,
FRAME_DATA_INDEX,
FRAME_INDEX_NBR
};
enum DEVICES_IDS
{
ID_MASTER, //Master Controller
ID_CONSOLE, //LCD Console
ID_PC, //PC
ID_AV_MUX, //Audio Video Multiplexer
ID_IR_REMOTE, //Infra red transmitter
ID_DEADBOLT_DEVICE,
ID_AV_RECEIVER,
ID_SMS_CLIENT,
ID_ETHERNET_VIRTUAL,
ID_SPRINKLER_DEVICE,
ID_SPRINKLER_INTERFACE,
ID_DEADBOLT_INTERFACE,
ID_AVRECEIVER_INTERFACE,
ID_CHALET_INTERFACE,
ID_CHALET_DEVICE,
ID_BOOTLOADER_VIRTUAL,
ID_NB_DEVICE_ID
};
// Commands definitions
enum MASTER_CMD
{
RX_MASTER_GET_STATUS,
TX_MASTER_STATUS,
TX_MASTER_ACK,
RX_MASTER_SET_NET_INFO,
RX_MASTER_GET_NET_INFO,
TX_MASTER_NET_INFO,
RX_MASTER_SEND_DEVICE_CMD,
TX_MASTER_SEND_DEVICE_CMD_ACK,
RX_MASTER_SET_WEATHER_INFO,
TX_MASTER_SET_WEATHER_INFO_ACK,
RX_MASTER_SET_MAIL_MSG,
TX_MASTER_SET_MAIL_MSG_ACK,
RX_MASTER_NEW_OUTLOOK_EMAILS,
TX_MASTER_NEW_OUTLOOK_EMAILS_ACK,
RX_MASTER_TODAYS_EVENTS,
TX_MASTER_TODAYS_EVENTS_ACK
};
//CONSOLE
enum CONSOLE_CMD
{
RX_CONSOLE_GET_STATUS,
TX_CONSOLE_STATUS,
TX_CONSOLE_ACK,
RX_START_CALIBRATION,
RX_GET_CONSOLE_EVENT_MSG,
TX_CONSOLE_EVENT_MSG,
RX_CONSOLE_SHOW_CALLER_ID,
RX_SET_TIME,
RX_SET_WEATHER,
RX_SEND_NEW_MAIL_MSG,
RX_SEND_NEW_MAIL_MSG_ACK,
RX_NEW_OUTLOOK_EMAILS,
TX_NEW_OUTLOOK_EMAILS_ACK,
RX_TODAYS_EVENTS,
TX_TODAYS_EVENTS_ACK,
LAST_CONSOLE_CMD
};
enum IR_REMOTE_CMDS
{
TX_IR_REMOTE_ACK = 1,
RX_GET_STATUS,
TX_REMOTE_STATUS,
RX_TRANSMIT_CMD,
RX_LEARN_IR_CMD,
TX_LEARN_IR_CMD_FINISHED,
RX_GET_IR_DATA,
TX_SEND_IR_DATA,
RX_SET_IR_CMD,
RX_SET_IR_DATA,
RX_GET_IR_CMD,
TX_SEND_IR_CMD,
MAX_IR_REMOTE_CMD
};
//The SMS remote interface commands
enum SMS_CLIENT_CMDS
{
SMS_CLIENT_DEVICE_ACK = 1,
SMS_CLIENT_DEVICE_STATUS_REQUEST,
SMS_CLIENT_DEVICE_STATUS_RESPONSE,
SMS_CLIENT_DEVICE_DID_INFO_REQUEST,
SMS_CLIENT_DEVICE_DID_INFO_RESPONSE,
SMS_CLIENT_DEVICE_GET_ALL_MSG_REQUEST,
SMS_CLIENT_DEVICE_GET_ALL_MSG_RESPONSE,
SMS_CLIENT_DEVICE_NEW_MSG_NOTIFICATION,
SMS_CLIENT_DEVICE_SEND_SMS_REQUEST,
SMS_CLIENT_DEVICE_SEND_SMS_ACK,
SMS_CLIENT_DEVICE_GET_CONTACTS_REQUEST,
SMS_CLIENT_DEVICE_GET_CONTACTS_RESPONSE,//12
SMS_CLIENT_DEVICE_CONTACTS_CHANGED_NOTIFICATION,
SMS_CLIENT_DEVICE_MAX_MSG
};
//The actual deadbolt device commands
enum DEADBOLT_CMDS
{
DEADBOLT_DEVICE_ACK = 1,
DEADBOLT_DEVICE_STATUS_REQUEST,
DEADBOLT_DEVICE_STATUS_RESPONSE,
DEADBOLT_DEVICE_GET_LOCKED_STATE_REQUEST,
DEADBOLT_DEVICE_LOCKED_STATE_RESPONSE,
DEADBOLT_DEVICE_GOTO_LOCKED_REQUEST,
DEADBOLT_DEVICE_GOTO_LOCKED_ACK,
DEADBOLT_DEVICE_GOTO_UNLOCKED_REQUEST,
DEADBOLT_DEVICE_GOTO_UNLOCKED_ACK,
DEADBOLT_DEVICE_GET_PASSWORDS_REQUEST,
DEADBOLT_DEVICE_GET_PASSWORDS_RESPONSE,
DEADBOLT_DEVICE_SET_PASSWORDS_REQUEST,
DEADBOLT_DEVICE_SET_PASSWORDS_ACK,
DEADBOLT_DEVICE_LOCK_EVENT,
MAX_DEADBOLT_DEVICE_CMD
};
//The actual sprinkler module device commands
enum SPRINKLER_DEVICE_CMDS
{
SPRINKLER_DEVICE_ACK = 1,
SPRINKLER_DEVICE_STATUS_REQUEST,
SPRINKLER_DEVICE_STATUS_RESPONSE,
SPRINKLER_DEVICE_SET_SPRINKLER_STATE_REQUEST,
SPRINKLER_DEVICE_SET_SPRINKLER_STATE_ACK,
SPRINKLER_DEVICE_GET_SPRINKLER_STATE_REQUEST,
SPRINKLER_DEVICE_GET_SPRINKLER_STATE_RESPONSE,
SPRINKLER_DEVICE_GET_WATER_FLOW_REQUEST,
SPRINKLER_DEVICE_GET_WATER_FLOW_RESPONSE,
SPRINKLER_DEVICE_GET_MOISTURE_REQUEST,
SPRINKLER_DEVICE_GET_MOISTURE_RESPONSE,
SPRINKLER_DEVICE_SET_PROGRAM_REQUEST,
SPRINKLER_DEVICE_SET_PROGRAM_ACK,
SPRINKLER_DEVICE_GET_PROGRAM_REQUEST,
SPRINKLER_DEVICE_GET_PROGRAM_RESPONSE,
SPRINKLER_DEVICE_SET_PARAMETERS_REQUEST,
SPRINKLER_DEVICE_SET_PARAMETERS_ACK,
SPRINKLER_DEVICE_GET_PARAMETERS_REQUEST,
SPRINKLER_DEVICE_GET_PARAMETERS_RESPONSE,
MAX_SPRINKLER_DEVICE_CMD
};
//The sprinkler interface commands
enum SPRINKLER_INTERFACE_CMDS
{
SPRINKLER_INTERFACE_ACK = 1,
SPRINKLER_INTERFACE_STATUS_REQUEST,
SPRINKLER_INTERFACE_STATUS_RESPONSE,
SPRINKLER_INTERFACE_GET_SPRINKLERS_REQUEST,
SPRINKLER_INTERFACE_GET_SPRINKLERS_RESPONSE,
SPRINKLER_INTERFACE_GET_SPRINKLER_DATA_REQUEST,
SPRINKLER_INTERFACE_GET_SPRINKLER_DATA_RESPONSE,
SPRINKLER_INTERFACE_SET_SPRINKLER_DATA_REQUEST,
SPRINKLER_INTERFACE_SET_SPRINKLER_DATA_ACK,
SPRINKLER_INTERFACE_GET_SPRINKLER_STATE_REQUEST,
SPRINKLER_INTERFACE_GET_SPRINKLER_STATE_RESPONSE,
SPRINKLER_INTERFACE_SET_SPRINKLER_STATE_REQUEST,
SPRINKLER_INTERFACE_SET_SPRINKLER_STATE_ACK,
MAX_SPRINKLER_INTERFACE_CMD
};
enum ETHERNET_NETWORK_VIRTUAL_CMDS
{
ETH_NETWK_DEVICE_INFO_REQUEST = 0xD0,
ETH_NETWK_DEVICE_INFO_RESPONSE,
ETH_NETWK_SET_DEVICE_INFO_ACK,
ETH_NETWK_CONNECTION_REFUSED,
MAX_ETHERNET_NETWORK_VIRTUAL_CMDS
};
enum AV_RECEIVER_INTERFACE_CMDS
{
AV_RECEIVER_INTERFACE_ACK = 1,
AV_RECEIVER_INTERFACE_GENERAL_STATUS_REQUEST,
AV_RECEIVER_INTERFACE_GENERAL_STATUS_RESPONSE,
AV_RECEIVER_INTERFACE_SET_MAIN_POWER_REQUEST,
AV_RECEIVER_INTERFACE_SET_MAIN_POWER_RESPONSE,
AV_RECEIVER_INTERFACE_SET_SPEAKERB_REQUEST,
AV_RECEIVER_INTERFACE_SET_SPEAKERB_RESPONSE,
AV_RECEIVER_INTERFACE_SET_SPEAKERA_REQUEST,
AV_RECEIVER_INTERFACE_SET_SPEAKERA_RESPONSE,
AV_RECEIVER_INTERFACE_SET_SPEAKERS_REQUEST,
AV_RECEIVER_INTERFACE_SET_SPEAKERS_RESPONSE,
AV_RECEIVER_INTERFACE_SEND_DIRECT_CMD_REQUEST,
AV_RECEIVER_INTERFACE_SEND_DIRECT_CMD_RESPONSE,
MAX_AV_RECEIVER_INTERFACE_CMD
};
enum CHALET_INTERFACE_CMDS
{
CHALET_INTERFACE_ACK = 1,
CHALET_INTERFACE_GENERAL_STATUS_REQUEST,
CHALET_INTERFACE_GENERAL_STATUS_RESPONSE,
CHALET_INTERFACE_AC_POWER_STATE_STATUS_REQUEST,
CHALET_INTERFACE_AC_POWER_STATE_STATUS_RESPONSE,
CHALET_INTERFACE_AC_POWER_SET_STATE_REQUEST,
CHALET_INTERFACE_AC_POWER_SET_STATE_RESPONSE,
CHALET_INTERFACE_BATTERY_VOLTAGE_REQUEST,
CHALET_INTERFACE_BATTERY_VOLTAGE_RESPONSE,
MAX_CHALET_INTERFACE_CMD
};
enum CHALET_CMDS
{
CHALET_ACK = 1,
CHALET_GENERAL_STATUS_REQUEST,
CHALET_GENERAL_STATUS_RESPONSE,
CHALET_AC_POWER_STATE_STATUS_REQUEST,
CHALET_AC_POWER_STATE_STATUS_RESPONSE,
CHALET_AC_POWER_SET_STATE_REQUEST,
CHALET_AC_POWER_SET_STATE_RESPONSE,
CHALET_BATTERY_VOLTAGE_REQUEST,
CHALET_BATTERY_VOLTAGE_RESPONSE,
CHALET_BATTERY_CURRENT_REQUEST,
CHALET_BATTERY_CURRENT_RESPONSE,
CHALET_WIFI_STATUS_REQUEST,
CHALET_WIFI_STATUS_RESPONSE,
CHALET_WIFI_SET_STATE_REQUEST,
CHALET_WIFI_SET_STATE_RESPONSE,
CHALET_DO_HARAKIRI_REQUEST,
CHALET_DO_HARAKIRI_CONFIRMATION,
CHALET_REBOOT_CPU_REQUEST,
CHALET_REBOOT_CPU_RESPONSE,
CHALET_GET_STORED_WIFI_SETTINGS_REQUEST,
CHALET_GET_STORED_WIFI_SETTINGS_RESPONSE,
CHALET_SET_STORED_WIFI_SETTINGS_REQUEST,
CHALET_SET_STORED_WIFI_SETTINGS_RESPONSE,
CHALET_GET_FIRMWARE_VERSION_REQUEST,
CHALET_GET_FIRMWARE_VERSION_RESPONSE,
CHALET_CLEAR_COMMS_STATISTICS_REQUEST,
CHALET_CLEAR_COMMS_STATISTICS_RESPONSE,
MAX_CHALET_CMD
};
enum BOOTLOADER_CMDS
{
BOOTLOADER_ACK = 1,
BOOTLOADER_HEARTBEAT_REQUEST,
BOOTLOADER_HEARTBEAT_RESPONSE,
BOOTLOADER_ERASE_BOOTLOADER_FLASH_REQUEST,
BOOTLOADER_ERASE_BOOTLOADER_FLASH_RESPONSE,
BOOTLOADER_ERASE_BOOTLOADER_FLASH_RESULT_RESPONSE,
BOOTLOADER_INIT_UPLOAD_REQUEST,
BOOTLOADER_INIT_UPLOAD_RESPONSE,
BOOTLOADER_GET_STATE_REQUEST,
BOOTLOADER_GET_STATE_RESPONSE,
BOOTLOADER_READY_FOR_DATA_RESPONSE,
BOOTLOADER_SEND_DATA_CHUNK_REQUEST,
BOOTLOADER_SEND_DATA_CHUNK_RESPONSE,
BOOTLOADER_UPLOAD_FINISHED_REQUEST,
BOOTLOADER_UPLOAD_FINISHED_RESPONSE,
BOOTLOADER_EXECUTE_UPGRAGE_REQUEST,
BOOTLOADER_EXECUTE_UPGRADE_RESPONSE,
BOOTLOADER_ABORT_OPERATION_REQUEST,
BOOTLOADER_ABORT_OPERATION_RESPONSE,
BOOTLOADER_SEND_FLASH_DATA_REQUEST,
BOOTLOADER_SEND_FLASH_DATA_RESPONSE,
BOOTLOADER_SEND_FLASH_DATA_CHUNK,
BOOTLOADER_SEND_FLASH_DATA_CHUNK_RESPONSE,
BOOTLOADER_CHECK_FLASH_FIRMW_INTEGRITY_REQUEST,
BOOTLOADER_CHECK_FLASH_FIRMW_INTEGRITY_RESPONSE,
BOOTLOADER_GET_STORED_FIRMWARE_INFO_REQUEST,
BOOTLOADER_GET_STORED_FIRMWARE_INFO_RESPONSE,
MAX_BOOTLOADER_CMD
};
#endif
+212
View File
@@ -0,0 +1,212 @@
#include "SDCardMgr.h"
#ifdef USE_FATFS
#include "FatFS/diskio.h"
#include "FatFS/ff.h"
FATFS FatFs; /* File system object */
FIL File[2]; /* File objects */
BYTE Buff[4096]; /* Working buffer */
#else
#include "sd_hw_ctl.h"
#include "FileSystem/fileio_lfn.h"
#endif
#include <stdio.h>
#include "timer.h"
int mSDCardState;
int mCardDetected;
int mCardMounted;
#ifdef USE_FATFS
#else
uint16_t mDriveLetter;
#endif
#ifdef USE_FATFS
int InitSDCard()
{
mSDCardState = SD_CARD_INIT_STATE;
mCardDetected = 0;
mCardMounted = 0;
return MountDrive();
}
int TickSDCard()
{
return 1;
}
int MountDrive()
{
FRESULT res;
res = f_mount(&FatFs, "", 0); /* Give a work area to the default drive */
if(!res)
{
printf("Could not mount SD card\n");
return 1;
}
else
{
printf("SD Card mounted successfuly");
}
return 0;
}
int IsDriveDetected()
{
return mCardDetected;
}
int IsDriveMounted()
{
return mCardMounted;
}
int ListRootDir()
{
FRESULT res;
DIR dir;
UINT i;
static FILINFO fno;
char path[] = "/";
res = f_opendir(&dir, path); /* Open the directory */
if (res == FR_OK) {
for (;;) {
res = f_readdir(&dir, &fno); /* Read a directory item */
if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
// if (fno.fattrib & AM_DIR) { /* It is a directory */
// i = strlen(path);
// sprintf(&path[i], "/%s", fno.fname);
// res = scan_files(path); /* Enter the directory */
// if (res != FR_OK) break;
// path[i] = 0;
// } else { /* It is a file. */
printf("%s/%s\n", path, fno.fname);
//}
}
f_closedir(&dir);
}
return 1;
}
#else
void FILEIO_GetTimestamp (FILEIO_TIMESTAMP * timeStamp)
{
timeStamp->date.bitfield.day = 6;
timeStamp->date.bitfield.month = 5;
timeStamp->date.bitfield.year = (2017 - 1980);
timeStamp->time.bitfield.hours = 9;
timeStamp->time.bitfield.minutes = 5;
timeStamp->time.bitfield.secondsDiv2 = 0;
timeStamp->timeMs = 0;
}
int InitSDCard()
{
SD_SPIConfigurePins();
FILEIO_Initialize();
mSDCardState = SD_CARD_INIT_STATE;
mCardDetected = 0;
mCardMounted = 0;
mDriveLetter = 'D';
TimerStart(SD_CARD_DETECT_TIMER,5000);
return 1;
}
int TickSDCard()
{
switch(mSDCardState)
{
case SD_CARD_INIT_STATE:
{
if(IsTimerExpired(SD_CARD_DETECT_TIMER))
{
if(FILEIO_MediaDetect(0, 0) == true)
{
mCardDetected = 1;
mSDCardState = SD_CARD_MOUNT_DRIVE_STATE;
printf("SD Card detected\n");
}
else
{
TimerStart(SD_CARD_DETECT_TIMER,999);
}
}
break;
}
case SD_CARD_MOUNT_DRIVE_STATE:
{
if(FILEIO_DriveMount(mDriveLetter, 0, 0) == FILEIO_ERROR_NONE)
{
mCardMounted = 1;
mSDCardState = SD_CARD_READY_STATE;
printf("SD Card mounted on drive %c\n",(unsigned char)mDriveLetter);
}
else
{
mSDCardState = SD_CARD_ERROR_MOUNTING_STATE;
printf("Error mounting SD card.\n");
}
break;
}
case SD_CARD_READY_STATE:
{
// if(FILEIO_MediaDetect(0, 0) == false)
// {
// mCardDetected = 0;
// mSDCardState = SD_CARD_INIT_STATE;
// }
break;
}
case SD_CARD_ERROR_MOUNTING_STATE:
{
//wait for removal of the sd card...
// if(FILEIO_MediaDetect(0, 0) == false)
// {
// mCardDetected = 0;
// mSDCardState = SD_CARD_INIT_STATE;
// printf("SD Card removed");
// }
break;
}
}
}
int MountDrive()
{
}
int IsDriveDetected()
{
return mCardDetected;
}
int IsDriveMounted()
{
return mCardMounted;
}
#endif
+45
View File
@@ -0,0 +1,45 @@
/*
* File: SDCardMgr.h
* Author: JF
*
* Created on May 18, 2017, 8:20 PM
*/
#ifndef SDCARDMGR_H
#define SDCARDMGR_H
#ifdef USE_FATFS
//#include "FatFS/diskio.h"
#else
#include "FileSystem/fileio_lfn.h"
#endif
enum eSDCardStates
{
SD_CARD_INIT_STATE,
SD_CARD_MOUNT_DRIVE_STATE,
SD_CARD_READY_STATE,
SD_CARD_ERROR_MOUNTING_STATE
};
#ifdef USE_FATFS
#else
void FILEIO_GetTimestamp(FILEIO_TIMESTAMP * timeStamp);
//void FILEIO_SETUP_HW();
#endif
int InitSDCard();
int MountDrive();
int IsDriveDetected();
int IsDriveMounted();
int TickSDCard();
int ListRootDir();
//void FILEIO_
#endif /* SDCARDMGR_H */
+20
View File
@@ -0,0 +1,20 @@
#include "define.h"
#include "BoardCfg.h"
#include "SPI.h"
unsigned char SPITransaction(unsigned char OutBuf, unsigned char BaudRate)
{
SPI2BRG = BaudRate;
// WIFI_SPI_SS_PIN = 0;
SPI2BUF = OutBuf;
while(!SPI2STATbits.SPIRBF);
OutBuf = SPI2BUF;
// WIFI_SPI_SS_PIN = 1;
return OutBuf;
}
+14
View File
@@ -0,0 +1,14 @@
/*
* File: SPI.h
* Author: JF
*
* Created on December 2, 2018, 3:36 PM
*/
#ifndef SPI_H
#define SPI_H
unsigned char SPITransaction(unsigned char OutBuf, unsigned char Baudrate);
#endif /* SPI_H */
+432
View File
@@ -0,0 +1,432 @@
#include "SPI_Flash.h"
#include "SPI.h"
#include "BoardCfg.h"
unsigned char mSPIFlashBaudrate;
unsigned char mSPIFlashHighSpeedBaudrate;
unsigned char mFlashSectorBuffer[SPI_FLASH_SECTOR_SIZE];
unsigned int mSPIFlashOK;
int InitSPIFlash()
{
FLASH_SS_PIN = 1;
mSPIFlashBaudrate = SPICalculateBRG(PERIPHERAL_FREQ, 25000000);
// mSPIFlashHighSpeedBaudrate = SPICalculateBRG(PERIPHERAL_FREQ, 50000000);
mSPIFlashHighSpeedBaudrate = SPICalculateBRG(PERIPHERAL_FREQ, 35000000);
mSPIFlashOK = 0;
}
int SPIFlashCheckAndConfigure()
{
if(SPIFlashCheckChipID() == RET_OK)
{
SPIFlashWriteEnable();
FLASH_SS_PIN = 0;
SPITransaction(SPI_FLASH_WRITE_STATUS_REG,mSPIFlashHighSpeedBaudrate);
SPITransaction(0x00,mSPIFlashHighSpeedBaudrate); //Configure for write enable the whole memory
FLASH_SS_PIN = 1;
SPIFlashReadStatusReg(1);
mSPIFlashOK = 1;
printf("SPI Flash configured\n");
return RET_OK;
}
mSPIFlashOK = 0;
printf("ERROR: SPI Flash not detected\n");
return RET_ERROR;
}
int SPIFlashIsPresent()
{
return mSPIFlashOK;
}
int SPIFlashWriteEnable()
{
FLASH_SS_PIN = 0;
SPITransaction(SPI_FLASH_WRITE_ENABLE,mSPIFlashHighSpeedBaudrate);
FLASH_SS_PIN = 1;
return RET_OK;
}
unsigned char SPIFlashReadStatusReg(int print)
{
unsigned char result;
FLASH_SS_PIN = 0;
result = SPITransaction(SPI_FLASH_READ_STATUS_REG,mSPIFlashBaudrate);
result = SPITransaction(0x00,mSPIFlashBaudrate); //get data
FLASH_SS_PIN = 1;
if(print)
{
printf("Flash status register : 0x%x\n",result);
}
return result;
}
int SPIFlashCheckBusy()
{
unsigned char status = SPIFlashReadStatusReg(0);
if((status & SPI_FLASH_BUSY_MASK) != 0)
{
return 1;
}
return 0;
}
int SPIFlashCheckChipID()
{
unsigned char VendorID, ChipID;
FLASH_SS_PIN = 0;
SPITransaction(SPI_FLASH_READ_ID,mSPIFlashBaudrate);
SPITransaction(0x00,mSPIFlashBaudrate);
SPITransaction(0x00,mSPIFlashBaudrate);
SPITransaction(0x00,mSPIFlashBaudrate); //Vendor address
VendorID = SPITransaction(0x00,mSPIFlashBaudrate); //Vendor ID, should be 0xBF
ChipID = SPITransaction(0x00,mSPIFlashBaudrate); //Device ID, should be 0x41
FLASH_SS_PIN = 1;
if(VendorID != SPI_FLASH_VENDOR_ID || ChipID != SPI_FLASH_CHIP_ID)
{
printf("SPI Flash detection FAILED. Vendor: 0x%x, Chip ID: 0x%x\n",VendorID,ChipID);
return RET_ERROR;
}
printf("SPI Flash detected. Vendor: 0x%x, Chip ID: 0x%x\n",VendorID,ChipID);
return RET_OK;
}
int SPIFlashReadBuffer(unsigned char *Buf, int Size, int StartAddress)
{
if(StartAddress + Size - 1 > SPI_FLASH_MAX_ADDRESS)
{
return RET_ERROR;
}
FLASH_SS_PIN = 0;
SPITransaction(SPI_FLASH_HI_SPEED_READ,mSPIFlashBaudrate);
SPITransaction(((StartAddress & 0xFF0000) >> 16),mSPIFlashHighSpeedBaudrate);
SPITransaction(((StartAddress & 0x00FF00) >> 8),mSPIFlashHighSpeedBaudrate);
SPITransaction((StartAddress & 0x0000FF),mSPIFlashHighSpeedBaudrate);
SPITransaction((0x00),mSPIFlashHighSpeedBaudrate); //Chip requires a dummy read in high speed
int i;
for(i = 0; i < Size; i++)
{
unsigned char tmp;
tmp =SPITransaction(0xDE,mSPIFlashHighSpeedBaudrate);
*Buf++ = tmp;
// *Buf++ = SPITransaction(0xDE,mSPIFlashHighSpeedBaudrate);
}
FLASH_SS_PIN = 1;
return RET_OK;
}
int SPIFlashEraseSector(int SectorAddress)
{
if(SectorAddress % SPI_FLASH_SECTOR_SIZE != 0) //Sectors are aligned on 0x1000
{
return RET_ERROR;
}
SPIFlashWriteEnable();
FLASH_SS_PIN = 0;
SPITransaction(SPI_FLASH_4KB_SECOTR_ERASE,mSPIFlashHighSpeedBaudrate);
SPITransaction(((SectorAddress & 0xFF0000) >> 16),mSPIFlashHighSpeedBaudrate);
SPITransaction(((SectorAddress & 0x00FF00) >> 8),mSPIFlashHighSpeedBaudrate);
SPITransaction((SectorAddress & 0x0000FF),mSPIFlashHighSpeedBaudrate);
FLASH_SS_PIN = 1;
SectorAddress++;
while( SPIFlashCheckBusy() == true);
//SPIFlashWriteEnable();
return RET_OK;
}
int SPIFlashErase64KSector(int SectorAddress, int Blocking)
{
if(SectorAddress % SPI_FLASH_64K_SECTOR_SIZE != 0) //Sectors are aligned on 0x1000
{
return RET_ERROR;
}
if((SectorAddress + SPI_FLASH_64K_SECTOR_SIZE - 1) > SPI_FLASH_MAX_ADDRESS)
{
return RET_ERROR;
}
SPIFlashWriteEnable();
FLASH_SS_PIN = 0;
SPITransaction(SPI_FLASH_64KB_BLOCK_ERASE,mSPIFlashHighSpeedBaudrate);
SPITransaction(((SectorAddress & 0xFF0000) >> 16),mSPIFlashHighSpeedBaudrate);
SPITransaction(((SectorAddress & 0x00FF00) >> 8),mSPIFlashHighSpeedBaudrate);
SPITransaction((SectorAddress & 0x0000FF),mSPIFlashHighSpeedBaudrate);
FLASH_SS_PIN = 1;
if(Blocking != 0)
{
while( SPIFlashCheckBusy() == true);
// SPIFlashWriteEnable();
}
return RET_OK;
}
int SPIFlashWriteSectorWorkingBuffer(int SectorAddress, int Erase)
{
if(SectorAddress % SPI_FLASH_SECTOR_SIZE != 0) //Sectors are aligned on 0x1000
{
return RET_ERROR;
}
if(Erase == 1)
{
SPIFlashEraseSector(SectorAddress);
}
unsigned char *DataPtr = &mFlashSectorBuffer[0];
int j;
for(j = 0; j < SPI_FLASH_SECTOR_SIZE; j++)
{
unsigned char curbyte;
curbyte = *DataPtr;
SPIFlashWriteEnable();
char Add1, Add2, Add3;
Add1 = (unsigned char)((SectorAddress & 0xFF0000) >> 16);
Add2 = ((unsigned char)((SectorAddress & 0x00FF00) >> 8));
Add3 = ((unsigned char)(SectorAddress & 0x0000FF));
int t;
t = 0;
FLASH_SS_PIN = 0;
SPITransaction(SPI_FLASH_BYTE_PROGRAM,mSPIFlashHighSpeedBaudrate);
// SPITransaction((unsigned char)((SectorAddress & 0xFF0000) >> 16),mSPIFlashHighSpeedBaudrate);
// SPITransaction((unsigned char)((SectorAddress & 0x00FF00) >> 8),mSPIFlashHighSpeedBaudrate);
// SPITransaction((unsigned char)(SectorAddress & 0x0000FF),mSPIFlashHighSpeedBaudrate);
SPITransaction(Add1,mSPIFlashHighSpeedBaudrate);
SPITransaction(Add2,mSPIFlashHighSpeedBaudrate);
SPITransaction(Add3,mSPIFlashHighSpeedBaudrate);
SPITransaction(curbyte,mSPIFlashHighSpeedBaudrate);
// SPITransaction(*DataPtr,mSPIFlashHighSpeedBaudrate);
FLASH_SS_PIN = 1;
DataPtr++;
SectorAddress++;
while( SPIFlashCheckBusy() == true);
}
return RET_OK;
}
int SPIFlashWriteByte(unsigned int ByteAddress, char byte, int blocking)
{
if(ByteAddress > SPI_FLASH_MAX_ADDRESS)
{
return RET_ERROR;
}
SPIFlashWriteEnable();
FLASH_SS_PIN = 0;
SPITransaction(SPI_FLASH_BYTE_PROGRAM,mSPIFlashHighSpeedBaudrate);
SPITransaction(((ByteAddress & 0xFF0000) >> 16),mSPIFlashHighSpeedBaudrate);
SPITransaction(((ByteAddress & 0x00FF00) >> 8),mSPIFlashHighSpeedBaudrate);
SPITransaction((ByteAddress & 0x0000FF),mSPIFlashHighSpeedBaudrate);
SPITransaction(byte,mSPIFlashHighSpeedBaudrate);
FLASH_SS_PIN = 1;
if(blocking)
{
while( SPIFlashCheckBusy() == true);
}
return RET_OK;
}
//int SPIFlashEraseSectorForWrite(unsigned char StartAddress, int Size)
//{
// //First, let's determine which sector to erase.
//
// int NbSectors = 1;
// int FirstSector = StartAddress / 0x1000;
// int LastSector = (StartAddress + Size) / 0x1000;
//
// if(LastSector > FirstSector)
// {
// NbSectors = LastSector - FirstSector;
// }
//
// int i;
// for(i = FirstSector; i < LastSector; i++ ) //Erase each sector one by one
// {
//
// }
//
//}
//int SPIFlashWriteBuffer(unsigned char *Buf, int Size, int StartAddress)
//{
// //First, we need to determine if the data overlaps or uses more than one sector
// //First, let's determine which sector to erase.
// int EndAddress = StartAddress + Size - 1;
// if(EndAddress > SPI_FLASH_MAX_ADDRESS)
// {
// return RET_ERROR;
// }
//
// int NbSectors = 1;
// int FirstSector = StartAddress / SPI_FLASH_SECTOR_SIZE;
// int LastSector = EndAddress / SPI_FLASH_SECTOR_SIZE;
//
// if(LastSector > FirstSector)
// {
// NbSectors = LastSector - FirstSector + 1;
// }
//
// int i;
// int FlashAddress = StartAddress;
// int CurSector = FirstSector;
// for(i = 0; i < NbSectors; i++ ) //Read, erase and write each sector one by one
// {
// //first we need to backup the data outside our buffer.
// //TODO: optimize
// int SectorStartAddress = CurSector++ * SPI_FLASH_SECTOR_SIZE;
// int SectorEndAddress = SectorStartAddress + SPI_FLASH_SECTOR_SIZE - 1;
// if(SectorEndAddress > EndAddress)
// {
// SectorEndAddress = EndAddress;
// }
//
// SPIFlashReadBuffer(mFlashSectorBuffer,SPI_FLASH_SECTOR_SIZE,SectorStartAddress); //Get local RAM buffer of the sector
//
// //Update the data to write.
// int RAMAddress = FlashAddress - SectorStartAddress;
// int RAMSectorSize = SectorEndAddress - FlashAddress + 1;
// FlashAddress += RAMSectorSize;
//
// unsigned char* RAMPtr = &mFlashSectorBuffer[RAMAddress];
// int j;
// for(j = 0; j < RAMSectorSize; j++)
// {
// *RAMPtr++ = *Buf++;
// }
//
// int SectorAddress = SectorStartAddress;
// RAMPtr = mFlashSectorBuffer;
//
// for(j = 0; j < SPI_FLASH_SECTOR_SIZE; j++)
// {
// SPIFlashWriteEnable();
//
// FLASH_SS_PIN = 0;
// SPITransaction(SPI_FLASH_BYTE_PROGRAM,mSPIFlashHighSpeedBaudrate);
// SPITransaction(((SectorAddress & 0xFF0000) >> 16),mSPIFlashBaudrate);
// SPITransaction(((SectorAddress & 0x00FF00) >> 8),mSPIFlashBaudrate);
// SPITransaction((SectorAddress & 0x0000FF),mSPIFlashBaudrate);
// SPITransaction(*RAMPtr++,mSPIFlashBaudrate);
// FLASH_SS_PIN = 1;
//
// SectorAddress++;
//
// while( SPIFlashCheckBusy() == true);
// }
// }
//}
int SPIFlashWriteBuffer(unsigned char *Buf, int Size, int StartAddress)
{
int CurDataFlashAddress, DataFlashEndAddress;
char *DataBufPtr, *WorkPagePtr;
int WriteFinished;
//Init stuff
WriteFinished = 0;
DataFlashEndAddress = StartAddress + Size; //Start + size means the data at "DataFlashEndAddress" should not be written.
CurDataFlashAddress = StartAddress;
DataBufPtr = Buf;
if(DataFlashEndAddress > SPI_FLASH_MAX_ADDRESS)
{
return RET_ERROR;
}
while(WriteFinished == 0)
{
//Determine the current sector start address.
int SectorStartAddress;
SectorStartAddress = ((CurDataFlashAddress / SPI_FLASH_SECTOR_SIZE) * SPI_FLASH_SECTOR_SIZE); //Weird but it works
//Load the sector in RAM working buffer
if(SPIFlashReadBuffer(mFlashSectorBuffer,SPI_FLASH_SECTOR_SIZE,SectorStartAddress) != RET_OK)
{
return RET_ERROR;
}
//Set the working buffer pointer to the right value.
WorkPagePtr = &mFlashSectorBuffer[CurDataFlashAddress - SectorStartAddress];
//Modify the working buffer with data to write.
int SectorFinished = 0;
while(SectorFinished == 0)
{
*WorkPagePtr++ = *DataBufPtr++;
CurDataFlashAddress++;
//Are we at the end of the buffer to write?
if(CurDataFlashAddress == DataFlashEndAddress)
{
SectorFinished = 1;
WriteFinished = 1;
// SPIFlashEraseSector(SectorStartAddress);
SPIFlashWriteSectorWorkingBuffer(SectorStartAddress,1);
break;
}
else if(CurDataFlashAddress % SPI_FLASH_SECTOR_SIZE == 0) //Are we at the beginning of the next sector?
{
SectorFinished = 1;
// SPIFlashEraseSector(SectorStartAddress);
SPIFlashWriteSectorWorkingBuffer(SectorStartAddress,1);
break;
}
}
}
return 1;
}
+49
View File
@@ -0,0 +1,49 @@
#ifndef SPI_FLASH_H /* Guard against multiple inclusion */
#define SPI_FLASH_H
#define SPI_FLASH_READ 0x03
#define SPI_FLASH_HI_SPEED_READ 0x0b
#define SPI_FLASH_4KB_SECOTR_ERASE 0x20
#define SPI_FLASH_32KB_BLOCK_ERASE 0x52
#define SPI_FLASH_64KB_BLOCK_ERASE 0xd8
#define SPI_FLASH_CHIP_ERASE 0x60
#define SPI_FLASH_BYTE_PROGRAM 0x02
#define SPI_FLASH_AAI_WORD_PROGRAM 0xad
#define SPI_FLASH_READ_STATUS_REG 0x05
#define SPI_FLASH_ENABLE_WRITE_STATUS_REG 0x50
#define SPI_FLASH_WRITE_STATUS_REG 0x01
#define SPI_FLASH_WRITE_ENABLE 0x06
#define SPI_FLASH_WRITE_DISABLE 0x04
#define SPI_FLASH_READ_ID 0x90
#define SPI_FLASH_READ_JEDEC_ID 0x9f
#define SPI_FLASH_ENABLE_SO_BUSY 0x70
#define SPI_FLASH_DISABLE_SO_BUSY 0x80
#define SPI_FLASH_BUSY_MASK 0x01
#define SPI_FLASH_VENDOR_ID 0xBF
#define SPI_FLASH_CHIP_ID 0x41
#define SPI_FLASH_MAX_ADDRESS 0x1FFFFF
#define SPI_FLASH_SECTOR_SIZE 0x1000
#define SPI_FLASH_64K_SECTOR_SIZE 0x10000
#define SPI_NB_SECTORS 0x1FF //511 sectors = SPI_FLASH_MAX_ADDRESS / SPI_FLASH_SECTOR_SIZE
int InitSPIFlash();
int SPIFlashCheckChipID();
unsigned char SPIFlashReadStatusReg(int print);
int SPIFlashCheckAndConfigure();
int SPIFlashReadBuffer(unsigned char *Buf, int Size, int StartAddress);
int SPIFlashCheckBusy();
int SPIFlashWriteEnable();
int SPIFlashEraseSector(int SectorAddress);
int SPIFlashErase64KSector(int SectorAddress, int Blocking);
int SPIFlashWriteSectorWorkingBuffer(int SectorAddress, int Erase);
int SPIFlashWriteBuffer(unsigned char *Buf, int Size, int StartAddress);
int SPIFlashWriteByte(unsigned int ByteAddress, char byte, int blocking);
int SPIFlashIsPresent();
#endif /* SPI_FLASH_H */
+7
View File
@@ -0,0 +1,7 @@
#include "define.h"
#include "Schedule.h"
void InitSchedule()
{
}
+14
View File
@@ -0,0 +1,14 @@
/*
* File: Schedule.h
* Author: JF
*
* Created on May 4, 2017, 1:16 PM
*/
#ifndef SCHEDULE_H
#define SCHEDULE_H
void InitSchedule();
#endif /* SCHEDULE_H */
+39
View File
@@ -0,0 +1,39 @@
/*******************************************************************************
* *
* Copyright 2012 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C header file.
*/
/* ************************************************************************** */
/* Revision:
### 20120516 JFM
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
/* ************************************************************************** */
/* Includes */
#include "define.h"
#include "Scheduler.h"
//----------------------------------------------------------------------------
void InitScheduler(void)
{
}
//----------------------------------------------------------------------------
//EOF
+48
View File
@@ -0,0 +1,48 @@
/*******************************************************************************
* *
* Copyright 2012 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C header file.
*/
/* ************************************************************************** */
/* Revision:
### 20120516 JFM
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
#ifndef SCHEDULER_H
#define SCHEDULER_H
/* ************************************************************************** */
/* Includes */
/* ************************************************************************** */
/* Defines */
/* ************************************************************************** */
/* Type definitions */
/* ************************************************************************** */
/* Prototypes */
void InitScheduler(void);
#endif
//EOF
+92
View File
@@ -0,0 +1,92 @@
#include "Syslog.h"
#include "define.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "terminal.h"
#include "WiFiCtrl.h"
#include "timer.h"
//#define SYSLOG_BUFFER_SIZE 1024
#define SYSLOG_BUFFER_SIZE 500
char mSyslogBuffer[SYSLOG_BUFFER_SIZE];
int mSyslogBufPtr;
int InitSyslog()
{
mSyslogBufPtr = 0;
memset(mSyslogBuffer,0,SYSLOG_BUFFER_SIZE);
TimerStart(SYSLOG_TX_TIMER,SYSLOG_TX_TIMEOUT);
}
void SyslogTick()
{
if(IsSyslogClientConnected() == 0)
{
mSyslogBufPtr = 0;
return;
}
if(mSyslogBufPtr != 0 && IsTimerExpired(SYSLOG_TX_TIMER) == 1)
{
SendSyslogData(mSyslogBuffer,mSyslogBufPtr);
mSyslogBufPtr = 0;
// if(mSyslogBufPtr >= 150)
// {
// SendSyslogData(mSyslogBuffer,150);
// mSyslogBufPtr -= 150;
//
// }
// else
// {
// SendSyslogData(mSyslogBuffer,mSyslogBufPtr);
// mSyslogBufPtr = 0;
// }
TimerStart(SYSLOG_TX_TIMER,SYSLOG_TX_TIMEOUT);
}
}
int SyslogNewByte(char byte)
{
if(IsSyslogClientConnected() == 0)
{
mSyslogBufPtr = 0;
return 0;
}
mSyslogBuffer[mSyslogBufPtr] = byte;
mSyslogBufPtr++;
if(mSyslogBufPtr == SYSLOG_BUFFER_SIZE)
{
SendSyslogData(mSyslogBuffer,SYSLOG_BUFFER_SIZE);
mSyslogBufPtr = 0;
}
TimerStart(SYSLOG_TX_TIMER,SYSLOG_TX_TIMEOUT);
return 1;
}
int SyslogNewString(char *string)
{
if(IsSyslogClientConnected() == 0)
{
mSyslogBufPtr = 0;
return 0;
}
SendSyslogData(string,strlen(string));
return 1;
}
int SyslogIsBufferEmpty()
{
if(mSyslogBufPtr == 0)
return RET_OK;
return RET_ERROR;
}
+14
View File
@@ -0,0 +1,14 @@
#ifndef SYSLOG_H
#define SYSLOG_H
#define SYSLOG_TX_TIMEOUT 200 //ms
int InitSyslog();
void SyslogTick();
int SyslogNewByte(char byte);
int SyslogNewString(char *string);
int SyslogIsBufferEmpty();
#endif
+95
View File
@@ -0,0 +1,95 @@
//#include <proc/p32mx440f256h.h>
#include "TC77.h"
#include "BoardCfg.h"
#include "timer.h"
short mDeviceID;
int TC77Configure()
{
TEMP_SENSOR_CS_PIN = 0;
//Execute a 16 bits read first.
SPI3BUF = 0xFF;
while(!SPI3STATbits.SPIRBF);
SPI3BUF = 0xFF;
while(!SPI3STATbits.SPIRBF);
//Now, write 0xFFFF to config register.
SPI3BUF = 0xFF;
while(!SPI3STATbits.SPIRBF);
SPI3BUF = 0xFF;
while(!SPI3STATbits.SPIRBF);
//Read Device ID
SPI3BUF = 0x00;
while(!SPI3STATbits.SPIRBF);
mDeviceID = SPI3BUF;
mDeviceID <<= 8;
SPI3BUF = 0xFF;
while(!SPI3STATbits.SPIRBF);
mDeviceID += SPI3BUF;
TEMP_SENSOR_CS_PIN = 1;
mDeviceID &= 0xFFFC;
if(mDeviceID != 0x5400)
{
return RET_ERROR;
}
Sleep(100);
//Device detected. Now, put the device in continuous read mode.
TEMP_SENSOR_CS_PIN = 0;
//Execute a 16 bits read first.
SPI3BUF = 0xFF;
while(!SPI3STATbits.SPIRBF);
SPI3BUF = 0xFF;
while(!SPI3STATbits.SPIRBF);
//Now, write 0x0000 to config register.
SPI3BUF = 0x00;
while(!SPI3STATbits.SPIRBF);
SPI3BUF = 0x00;
while(!SPI3STATbits.SPIRBF);
TEMP_SENSOR_CS_PIN = 1;
return RET_OK;
}
float TC77GetActualTemp()
{
short RawTemp = 0;
float Temp;
TEMP_SENSOR_CS_PIN = 0;
//Read 16 bits.
SPI3BUF = 0x00;
while(!SPI3STATbits.SPIRBF);
RawTemp = SPI3BUF;
RawTemp <<= 8;
SPI3BUF = 0xFF;
while(!SPI3STATbits.SPIRBF);
RawTemp += SPI3BUF;
TEMP_SENSOR_CS_PIN = 1;
RawTemp &= 0xFFF8; //Get rid of useless 3 LSB
//RawTemp >>= 3;
Temp = ((float)0.0625 * (float)RawTemp);
Temp /= 8;
return Temp;
}
short TC77GetDeviceID()
{
return mDeviceID;
}
+18
View File
@@ -0,0 +1,18 @@
/*
* File:
* Author: JF
*
* Created on November 30, 2018, 7:33 PM
*/
#ifndef TC77_H
#define TC77_H
#include "define.h"
int TC77Configure();
float TC77GetActualTemp();
short TC77GetDeviceID();
#endif /* TC77_H */
+59
View File
@@ -0,0 +1,59 @@
#include "define.h"
#include "TCPServer.h"
#ifdef USE_WINC1500
#else
#include "TCPIP_Stack/TCPIP.h"
#endif
#include <stdio.h>
BYTE vTelnetSession;
WORD w, w2;
#ifdef USE_WINC1500
#else
TCP_SOCKET MyTCPSocket;
#endif
int OpenTCPServer()
{
#ifdef USE_WINC1500
return 0;
#else
MyTCPSocket = TCPOpen(0, TCP_OPEN_SERVER, 1212, TCP_PURPOSE_GENERIC_TCP_SERVER);
if (MyTCPSocket == INVALID_SOCKET)
return 0;
return 1;
#endif
}
void TickTCPServer()
{
BYTE i;
#ifdef USE_WINC1500
#else
WORD size = TCPIsGetReady(MyTCPSocket);
if (size != 0)
{
printf("Server Rx %d bytes\n",size);
BYTE buf[100];
TCPGetArray(MyTCPSocket, buf,size);
TCPPutArray(MyTCPSocket,buf,size);
// switch (i)
// {
// case 'q':
// case 'Q':
// {
// TCPPutString(MySocket, "Bye\n");
// TCPDisconnect(MySocket);
// break;
// }
// default:
// {
// TCPPut(MySocket,i);
// }f
// }
}
#endif
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef TCPSERVER_H
#define TCPSERVER_H
int OpenTCPServer();
void TickTCPServer();
#endif
+38
View File
@@ -0,0 +1,38 @@
//#include <proc/p32mx440f256h.h>
#include "TemperatureSensor.h"
#include "BoardCfg.h"
#include "TC77.h"
#include "timer.h"
void InitTempSensor()
{
ActualTemp = 0xBAADBEEF;
TimerStart(TEMP_SENSOR_REFRESH_TIMER,1000);
}
int TempSensorCheckAndConfigure()
{
if(TC77Configure() == RET_OK)
{
ActualTemp = TC77GetActualTemp();
return RET_OK;
}
return RET_ERROR;
}
float TempSensorGetTemp()
{
return ActualTemp;
}
void TickTempSensor()
{
if(IsTimerExpired(TEMP_SENSOR_REFRESH_TIMER))
{
ActualTemp = TC77GetActualTemp();
TimerStart(TEMP_SENSOR_REFRESH_TIMER,1000);
// printf("Temperature: %f\n",ActualTemp);
}
}
+24
View File
@@ -0,0 +1,24 @@
/*
* File: ChaletPowerRelay.h
* Author: JF
*
* Created on November 30, 2018, 7:33 PM
*/
#ifndef TEMPERATURESENSOR_H
#define TEMPERATURESENSOR_H
#include "define.h"
float ActualTemp;
void InitTempSensor();
int TempSensorCheckAndConfigure();
float TempSensorGetTemp();
void TickTempSensor();
#endif /* TEMPERATURESENSOR_H */
+527
View File
@@ -0,0 +1,527 @@
/*
Description:
This is a template file for standard C header file.
*/
/* ************************************************************************** */
/* Revision:
### 20120607 JFM
Original version.
### 20120607 Initial, Bug Identification
Change description.
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "terminal.h"
#include "define.h"
#include "WiFiCtrl.h"
#include "LedLightCtrl.h"
#include "ChaletPowerRelay.h"
#include "BatteryMonitor.h"
#include "BootloaderInterface.h"
//#include "SDCardMgr.h"
#ifdef TERMINAL_USE_TELNET
#include "TCPIP_Stack/Telnet.h"
#endif
#define TerminalPrint(fmt, ...) \
do { sprintf(TerminalWorkString, fmt, __VA_ARGS__); \
TerminalPrintString(TerminalWorkString);} while (0)
char TerminalDataBuf[TERMINAL_STRING_LENGTH];
char TerminalPrevDataBuf[TERMINAL_STRING_LENGTH];
char TerminalWorkString[TERMINAL_STRING_LENGTH];
char *TerminalDataPtr;
int mTerminalPendingAction;
BOOL mTerminalOpened;
int mTerminalTickState;
static BYTE mHelpString[] = "Here is the list of the available commands:\n\r\n\r"
"help : Shows this window\n\r"
"\npower [state] Set chalet's 12V Inverter feed power state. This command controls the main power relay\n"
" - Available [state] argument are: on\n"
" off\n"
"\nwifi [command] control ChaletDuino's WiFi module state%\n"
" - Available [command] argument are: on (turns ON module)\n"
" off (turns OFF module)\n"
" status (returns current status)\n"
"\nbattery [sensor] returns current battery sensors readings\n"
" - Available [sensor] argument are: voltage\n"
" current\n"
" soc (state of charge)\n"
" Empty [sensor] argument prints all values\n"
"\nstatus : get general system status\n"
"\nbootloader [command] : bootloader mode control\n"
" - Available [command] argument are: start (enable bootloader and opens port)\n"
" stop (disables bootloader if not busy)\n"
" state (prints actual state of the bootloader)\n"
//"\ndebug : print some real-time stuff..."
"\nHave a good day!\n";
BYTE *mHelpStringPtr;
void InitTerminal(void)
{
TerminalDataPtr = &TerminalDataBuf[0];
memset(TerminalDataBuf,0,sizeof(TerminalDataBuf));
memset(TerminalPrevDataBuf,'\0',sizeof(TerminalPrevDataBuf));
memset(TerminalWorkString,'\0',sizeof(TerminalWorkString));
mTerminalPendingAction = TERMINAL_ACTION_NONE;
}
void TickTerminal()
{
switch(mTerminalPendingAction)
{
case TERMINAL_ACTION_NONE:
{
break;
}
case TERMINAL_ACTION_TURN_OFF_WIFI:
{
mTerminalPendingAction = TERMINAL_ACTION_NONE;
TurnOFFWiFi();
break;
}
}
}
void RxTerminalBuf(uint8* DataBuf, int size)
{
if(DataBuf != 0)
{
int i = 0;
for(i = 0; i < size; i++)
{
RxTerminalData(*DataBuf++);
}
}
}
void RxTerminalData(unsigned char Data)
{
// sTerminalPrint(TerminalWorkString,"%c",Data);
// TerminalPrintString(TerminalWorkString);
if(Data == 0x0D) //enter
{
//TerminalPrint("\n\r");
TerminalPrintString("\n\r\0");
if(strlen(TerminalDataBuf) != 0)
{
strcpy(TerminalPrevDataBuf,TerminalDataBuf);
ParseNewBuffer();
}
TerminalDataPtr = &TerminalDataBuf[0];
memset(TerminalDataBuf,'\0',sizeof(TerminalDataBuf));
}
else if(Data == 0x08 || Data == 0x7F) //backspace
{
// TerminalPrint("%c",Data);
TerminalPrintChar(Data);
if(TerminalDataPtr != &TerminalDataBuf[0])
{
TerminalDataPtr--;
*TerminalDataPtr = '\0';
}
}
// else if(Data == 0x1B) //Up key
// {
// //memcpy(TerminalDataBuf,TerminalPrevDataBuf,strlen(TerminalPrevDataBuf)-1);
// strcpy(TerminalDataBuf,TerminalPrevDataBuf);
// TerminalPrint("%s",TerminalDataBuf);
// }
else
{
//TerminalPrint("%c",Data);
TerminalPrintChar(Data);
if(TerminalDataPtr < &TerminalDataBuf[TERMINAL_STRING_LENGTH])
{
*TerminalDataPtr = Data;
TerminalDataPtr++;
}
}
}
void ParseNewBuffer(void)
{
char mCmdString[30], mDataString1[30], mDataString2[30], mDataString3[30],mDataString4[30];
memset(mCmdString,'\0',sizeof(mCmdString));
memset(mDataString1,'\0',sizeof(mDataString1));
memset(mDataString2,'\0',sizeof(mDataString2));
memset(mDataString3,'\0',sizeof(mDataString3));
memset(mDataString4,'\0',sizeof(mDataString4));
sscanf(TerminalDataBuf,"%s %s %s %s %s",mCmdString, mDataString1, mDataString2, mDataString3,mDataString4);
if(strncmp(mCmdString,"help",strlen("help")) == 0)
{
mHelpStringPtr = mHelpString;
static BYTE* Ptr= mHelpString;
SendTerminalData(mHelpString,strlen(mHelpString));
Ptr = mHelpStringPtr;
}
else if(strncmp(mCmdString,"power",strlen("power")) == 0)
{
if(strlen(mDataString1) == 0)
{
TerminalPrintString("\n[state] parameter is invalid. Type 'help' for more info\n");
return;
}
if(strncmp(mDataString1,"on",strlen("on")) == 0)
{
TerminalPrintString("Turning chalet's inverter ON\n");
ChaletPowerRelayTurnOn();
}
else if(strncmp(mDataString1,"off",strlen("off")) == 0)
{
TerminalPrintString("Turning chalet's inverter OFF\n");
ChaletPowerRelayTurnOff();
}
else
{
TerminalPrintString("\n[state] parameter is invalid. Type 'help' for valid values\n");
}
TerminalPrintString("\n");
}
else if(strncmp(mCmdString,"wifi",strlen("wifi")) == 0)
{
if(strlen(mDataString1) == 0)
{
TerminalPrintString("\n[value] parameter is invalid. Type 'help' for more info\n");
return;
}
if(strncmp(mDataString1,"on",strlen("on")) == 0)
{
if(GetWiFiSate() != WIFI_CONNECTED_STATE)
{
TerminalPrintString("Turning WiFi module ON\n");
InitWiFi();
}
else
{
TerminalPrintString("WiFi already connected...\n");
}
}
else if(strncmp(mDataString1,"off",strlen("off")) == 0)
{
if(GetWiFiSate() != WIFI_MODULE_OFF_STATE)
{
TerminalPrintString("Turning WiFi module OFF... Goodbye!\n");
//TurnOFFWiFi();
mTerminalPendingAction = TERMINAL_ACTION_TURN_OFF_WIFI;
}
else
{
TerminalPrintString("WiFi module already OFF... that's weird!\n");
}
}
else if(strncmp(mDataString1,"status",strlen("status")) == 0)
{
switch (GetWiFiSate())
{
case WIFI_MODULE_OFF_STATE:
{
TerminalPrintString("WiFi module OFF\n");
break;
}
case WIFI_CONNECTED_STATE:
{
TerminalPrintString("WiFi Connected\n");
break;
}
case WIFI_DISCONNECTED_STATE:
{
TerminalPrintString("WiFi Disconnected\n");
break;
}
case WIFI_INIT_ERROR_STATE:
{
TerminalPrintString("WiFi ERROR\n");
break;
}
case WIFI_UNKNOWN_STATE:
{
TerminalPrintString("WiFi state Unknown!\n");
break;
}
}
}
TerminalPrintString("\n");
}
else if(strncmp(mCmdString,"battery",strlen("battery")) == 0)
{
if(strlen(mDataString1) == 0)
{
char voltage[15];
sprintf(voltage,"%f",GetBatteryVoltage());
TerminalPrintString("Battery Voltage: ");
TerminalPrintString(voltage);
TerminalPrintString("\n");
char current[15];
sprintf(current,"%d",GetSolarPanelCurrent());
TerminalPrintString("Battery charge current: ");
TerminalPrintString(current);
TerminalPrintString("mA\n");
return;
}
if(strncmp(mDataString1,"voltage",strlen("voltage")) == 0)
{
char voltage[15];
sprintf(voltage,"%f",GetBatteryVoltage());
TerminalPrintString("Battery Voltage: ");
TerminalPrintString(voltage);
TerminalPrintString("\n");
}
else if(strncmp(mDataString1,"current",strlen("current")) == 0)
{
char current[15];
sprintf(current,"%d",GetSolarPanelCurrent());
TerminalPrintString("Battery charge current: ");
TerminalPrintString(current);
TerminalPrintString("mA\n");
}
else if(strncmp(mDataString1,"soc",strlen("soc")) == 0)
{
char SOC[15];
sprintf(SOC,"%d",GetBatterySOC());
TerminalPrintString("Battery SOC: ");
// TerminalPrintString(SOC);
TerminalPrintString("%\n");
}
TerminalPrintString("\n");
}
else if(strncmp(mCmdString,"status",strlen("status")) == 0)
{
// TerminalPrintString("General status:\nBattery: TBD \nWiFi: TBD\nOther Stuff: TBD\n");
TerminalPrintString("General status:\n");
if(GetChaletPowerRelayState() == CHALET_POWER_RELAY_OFF_STATE)
{
TerminalPrintString("Inverter power relay: OFF\n");
}
else if(GetChaletPowerRelayState() == CHALET_POWER_RELAY_ON_STATE)
{
TerminalPrintString("Inverter power relay: ON\n");
}
else
{
TerminalPrintString("Inverter power relay: UNKNOWN\n");
}
switch(GetWiFiSate())
{
case WIFI_MODULE_OFF_STATE:
{
TerminalPrintString("WiFi: Module is turned OFF\n");
break;
}
case WIFI_CONNECTED_STATE:
{
TerminalPrintString("WiFi: Connected to AP\n");
break;
}
case WIFI_DISCONNECTED_STATE:
{
TerminalPrintString("WiFi: Disconnected from AP\n");
break;
}
case WIFI_INIT_ERROR_STATE:
{
TerminalPrintString("WiFi: Module initialization error\n");
break;
}
case WIFI_UNKNOWN_STATE:
default:
{
TerminalPrintString("WiFi: Unknown state\n");
break;
}
}
char voltage[15];
memset(voltage,0,15);
sprintf(voltage,"%.2f",GetBatteryVoltage());
TerminalPrintString("Battery Voltage: ");
TerminalPrintString(voltage);
TerminalPrintString("V\n");
char current[15];
memset(current,0,15);
sprintf(current,"%dmA\n",GetSolarPanelCurrent());
TerminalPrintString("Battery charge current: ");
TerminalPrintString(current);
//TerminalPrintString("mA\n");
Sleep(100);
char SOC[15];
memset(SOC,0,15);
sprintf(SOC,"%d%%\n",GetBatterySOC());
TerminalPrintString("Battery SOC: ");
TerminalPrintString(SOC);
// TerminalPrintString("\n");
TerminalPrintString("\n");
}
else if(strncmp(mCmdString,"bootloader",strlen("bootloader")) == 0)
{
if(strlen(mDataString1) == 0)
{
TerminalPrintString("\n[command] parameter is invalid. Type 'help' for more info\n");
return;
}
if(strncmp(mDataString1,"start",strlen("start")) == 0)
{
//start bootloader server
// OpenBootloaderServer();
BootloaderActivateBootloader();
TerminalPrintString("Activating bootloader\n");
}
else if(strncmp(mDataString1,"stop",strlen("stop")) == 0)
{
//CloseBootloaderServer();
TerminalPrintString("Deactivating bootloader\n");
BootloaderDeactivateBootloader();
}
else if(strncmp(mDataString1,"status",strlen("status")) == 0)
{
if(IsBootloaderClientConnected())
{
TerminalPrintString("\nBootloader client connected\n");
return;
}
else
if(IsBootloaderClientConnected())
{
TerminalPrintString("\nBootloader client not connected\n");
return;
}
}
}
else if(strncmp(mCmdString,"debug",strlen(mCmdString)) == 0)
{
// if(strlen(mDataString1) == 0)
// {
// TerminalPrintString("\n[subsystem] parameter is invalid. Type 'help' for more info\n");
// return;
// }
// if(strlen(mDataString2) == 0)
// {
// TerminalPrintString("\n[timeout] parameter is invalid. Type 'help' for more info\n");
// return;
// }
//
// unsigned int timeout = atoi(mDataString2);
// if(timeout != 0 && timeout < 100 && timeout > 5000)
// {
// TerminalPrint("[timeout] value must be between 100 & 5000. Current value: %d",timeout);
// return;
// }
//
// if(strncmp(mDataString1,"valve",strlen("valve")) == 0)
// {
// // TerminalPrintValveStatus();
// TerminalPrintString("Debug valve not implemented\n");
// }
// else if(strncmp(mDataString1,"flow",strlen("flow")) == 0)
// {
// if(timeout == 0)
// {
// TerminalPrintString("Flow debugging stopped\n");
// StopDebugFlowMeter();
// }
// else
// {
// TerminalPrintString("OK\n");
// StartDebugFlowMeter(timeout);
// }
// }
// else if(strncmp(mDataString1,"hygro",strlen("hygro")) == 0)
// {
// TerminalPrintString("Debug hygro not implemented\n");
// }
}
else
TerminalPrintString("Unknown command\n\n");
}
void TerminalPrintString(char *str)
{
#ifdef USE_WINC1500
SendTerminalData(str,strlen(str));
#else
#ifdef TERMINAL_USE_TCP_SERVER
TCPPutString(mTerminalSocket, str);
#endif
#endif
}
void TerminalPrintChar(char byte)
{
#ifdef USE_WINC1500
SentTerminalByte(byte);
#else
#ifdef TERMINAL_USE_TCP_SERVER
TCPPut(mTerminalSocket,byte);
#endif
#endif
}
void TerminalStateMachine(void)
{
}
//
//void TerminalPrintValveStatus()
//{
// if(GetValveState() == VALVE_ON)
// {
// TerminalPrintString("The valve is ON\n");
// }
// else
// {
// TerminalPrintString("The valve is OFF\n");
// }
//}
//
//void TerminalPrintFlowStatus()
//{
// unsigned int Flow = GetCurrentFlow();
// TerminalPrint("Flow: %d\n",Flow);;
//}
//
//void TerminalPrintHygroStatus(int unit)
//{
// TerminalPrint("Hygro %d: ?\n",unit);
//}
//
//EOf
+67
View File
@@ -0,0 +1,67 @@
/*******************************************************************************
* *
* Copyright 2012 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C header file.
*/
/* ************************************************************************** */
/* Revision:
### YYYYMMDD JFM
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
#define TERMINAL_STRING_LENGTH 300
#define USE_WINC1500
enum eTerminalCmds
{
HELP_CMD,
PWM_CMD,
SET_CMD,
MAX_CMD
};
enum eTerimnalTickStates
{
TERMINAL_INIT_STATE,
TERMINAL_RUN_STATE
};
enum eTerminalActions
{
TERMINAL_ACTION_NONE = 0,
TERMINAL_ACTION_TURN_OFF_WIFI,
TERMINAL_ACTION_MAX
};
void InitTerminal(void);
void RxTerminalData(unsigned char Data);
void RxTerminalBuf(unsigned char *DataBuf, int size);
void ParseNewBuffer(void);
void TerminalStateMachine(void);
void TickTerminal(void);
void TerminalPrintString(char *str);
void TerminalPrintChar(char byte);
void TerminalPrintValveStatus();
void TerminalPrintFlowStatus();
void TerminalPrintHygroStatus(int unit);
//EOF
+699
View File
@@ -0,0 +1,699 @@
/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C code file.
*/
/* ************************************************************************** */
/* ¤Revision:
000 20100616 JFM,
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
/* ************************************************************************** */
/* Includes */
#include "define.h"
#include "Uart.h"
#include "Internaluart.h"
#include <stdio.h>
#include <string.h>
//#include "Watchdog.h"
#ifndef NO_EXTERNAL_UART
#include "sc16IS740Driver.h"
#endif
#include "digitalio.h"
//#include "DriveProtocol.h"
#include "terminal.h"
/* ************************************************************************** */
/* Local variables */
stUartData astUartData[MAX_UART_HANDLE];
const char *gUartStrings[MAX_UART_HANDLE] = { "PRINTF" //UART_1
//,"CU", //UART_2
// ,"CONSOLE" //UART_3
};
/* ************************************************************************** */
/* Private function prototypes */
//void _mon_putc(char c); //override from stdio to redirect stdout on uart 3B
//void _mon_write (const char * s, unsigned int count);
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void InitUart(void)
{
int i;
InternalUartInit();
//InitSC16S740();
memset(&astUartData,0,sizeof(astUartData));
for(i = 0; i < MAX_UART_HANDLE; i++)
{
astUartData[i].iDataPending = 0; //This flag is 0 when : TxPtr == RxPtr OR Uart is transmitting.
astUartData[i].pcTxInPtr = &astUartData[i].acTxCircularBuffer[0];
astUartData[i].pcTxOutPtr = &astUartData[i].acTxCircularBuffer[0];
//memset(&astUartData[i].acTxCircularBuffer[0],0xDE,UART_MAX_TX_BUFF_SIZE);
astUartData[i].pcRxInDataPtr = astUartData[i].pcRxOutDataPtr = &astUartData[i].acRxCircularBuffer[0];
astUartData[i].iNbRxFIFOPendingBytes = 0;
}
//This is a physical mapping of the UARTS.
//DO NOT CHANGE assignments unless hardware changed !
//
astUartData[UART_1].iIsInternal = 1;
astUartData[UART_1].iPhysicalUartPort = INTERNAL_UART_PORT_2; // (232)
// astUartData[UART_2].iIsInternal = 1;
//astUartData[UART_2].iPhysicalUartPort = INTERNAL_UART_PORT_2; // (232)
#ifndef NO_EXTERNAL_UART
astUartData[UART_3].iIsInternal = 0;
astUartData[UART_3].iPhysicalUartPort = EXT_UART_1; // (SPI - 232 daughter board)
#endif
setbuf(stdout,NULL); //to use printf without \r
fflush(stdout);
UartOpenComPort(NETWORK_UART_PORT,9600,UART_ONE_STOP_BIT,UART_NO_PARITY); //Open console port
#ifdef USE_PRINTF
//UartOpenComPort(CONSOLE_UART_PORT,115200,UART_ONE_STOP_BIT,UART_NO_PARITY); //Open console port
#endif
}
//-----------------------------------------------------------------------------
int UartResetPort(int p_iUartHandle)
{
if(p_iUartHandle > MAX_UART_HANDLE)
return 0;
//reset the port data structures...
astUartData[p_iUartHandle].iDataPending = 0; //This flag is 0 when : TxPtr == RxPtr OR Uart is transmitting.
astUartData[p_iUartHandle].pcTxInPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0];
astUartData[p_iUartHandle].pcTxOutPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0];
astUartData[p_iUartHandle].pcRxInDataPtr = astUartData[p_iUartHandle].pcRxOutDataPtr = &astUartData[p_iUartHandle].acRxCircularBuffer[0];
astUartData[p_iUartHandle].iNbRxFIFOPendingBytes = 0;
if(astUartData[UART_1].iIsInternal == 1)
{
switch(astUartData[p_iUartHandle].iPhysicalUartPort)
{
case INTERNAL_UART_PORT_1:
{
ResetUart1();
break;
}
case INTERNAL_UART_PORT_2:
{
ResetUart2();
break;
}
default:
break;
}
}
else
{
#ifndef NO_EXTERNAL_UART
switch(astUartData[p_iUartHandle].iPhysicalUartPort)
{
case EXT_UART_1:
{
break;
}
default:
break;
}
#endif
}
return 1;
}
//-----------------------------------------------------------------------------
int UartOpenComPort(int p_iUartHandle, int p_iBaudRate, int p_iNbStopBits, int p_iParityEnable)
{
int iStopbits,iParity,iRet;
if(p_iUartHandle >= MAX_UART_HANDLE || p_iUartHandle < 0)
return UART_INVALID_HANDLE;
if(astUartData[p_iUartHandle].iIsInternal == 1)
{
switch(p_iNbStopBits)
{
case UART_ONE_STOP_BIT:
case UART_ONE_HALF_STOP_BIT: //1½ stop bits doesn't exist for internal uart
{
iStopbits = INT_UART_ONE_STOP_BIT;
break;
}
case UART_TWO_STOP_BITS:
{
iStopbits = INT_UART_TWO_STOP_BITS;
break;
}
}
switch(p_iParityEnable)
{
case UART_NO_PARITY:
{
iParity = INT_UART_NO_PARITY;
break;
}
case UART_EVEN_PARITY:
{
iParity = INT_UART_EVEN_PARITY;
break;
}
case UART_ODD_PARTIY:
{
iParity = INT_UART_ODD_PARITY;
break;
}
}
iRet = OpenInternalPort(astUartData[p_iUartHandle].iPhysicalUartPort,
p_iUartHandle,
&astUartData[p_iUartHandle].acTxCircularBuffer[0],
&astUartData[p_iUartHandle].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE-1],
p_iBaudRate,
iStopbits,
iParity);
}
#ifndef NO_EXTERNAL_UART
else
{
switch(p_iNbStopBits)
{
case UART_ONE_STOP_BIT:
{
iStopbits = ONE_STOP_BIT;
break;
}
case UART_ONE_HALF_STOP_BIT: //1½ stop bits doesn't exist for internal uart
{
iStopbits = ONE_HALF_STOP_BIT;
break;
}
case UART_TWO_STOP_BITS:
{
iStopbits = TWO_STOP_BITS;
break;
}
}
switch(p_iParityEnable)
{
case UART_NO_PARITY:
{
iParity = NO_PARITY;
break;
}
case UART_EVEN_PARITY:
{
iParity = EVEN_PARITY;
break;
}
case UART_ODD_PARTIY:
{
iParity = ODD_PARITY;
break;
}
}
iRet = OpenExternalPort(astUartData[p_iUartHandle].iPhysicalUartPort,
p_iUartHandle,
&astUartData[p_iUartHandle].acTxCircularBuffer[0],
&astUartData[p_iUartHandle].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE-1],
p_iBaudRate,
iStopbits,
iParity);
}
#endif
return iRet;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//All the uart callback function assignment must be done here !!!
//This must be changed if hardware changes or if port assignment is changed !!!
//
int UartReceiveData(int p_iUartHandle, char *p_pcBuffer, int p_iSize)
{
int i;
stUartData *p_stUartDatPtr = &astUartData[p_iUartHandle];
if(p_iUartHandle < 0 && p_iUartHandle >= MAX_UART_HANDLE)
{
//TODO: Flag a logic error !
return 0;
}
for(i = 0; i < p_iSize; i++)
{
*p_stUartDatPtr->pcRxInDataPtr++ = *p_pcBuffer++;
if(p_stUartDatPtr->pcRxInDataPtr > &p_stUartDatPtr->acRxCircularBuffer[UART_MAX_RX_BUFF_SIZE-1])
{
p_stUartDatPtr->pcRxInDataPtr = &p_stUartDatPtr->acRxCircularBuffer[0]; //wrap pointer
// printf("Wrap\n");
}
}
p_stUartDatPtr->iNbRxFIFOPendingBytes += p_iSize;
if(p_stUartDatPtr->iNbRxFIFOPendingBytes >= UART_MAX_RX_BUFF_SIZE)
PRINTF("RX FIFO Overflow\n");
/* switch(p_iUartHandle)
{
case UART_0:
{
break;
}
case UART_1:
{
break;
}
case UART_2:
{
break;
}
case UART_3:
{
break;
}
case UART_4:
{
break;
}
case UART_5:
{
break;
}
} */
return 1;
}
int UartGetPendingDataSize(int iUartHandle)
{
stUartData *p_stUartDatPtr = &astUartData[iUartHandle];
if(p_stUartDatPtr->pcRxInDataPtr == p_stUartDatPtr->pcRxOutDataPtr)
{
return 0;
}
else if(p_stUartDatPtr->pcRxOutDataPtr < p_stUartDatPtr->pcRxInDataPtr)
{
return(p_stUartDatPtr->pcRxInDataPtr - p_stUartDatPtr->pcRxOutDataPtr);
}
else
{
int size = &p_stUartDatPtr->acRxCircularBuffer[UART_MAX_RX_BUFF_SIZE-1] - p_stUartDatPtr->pcRxOutDataPtr;
size += p_stUartDatPtr->pcRxInDataPtr - &p_stUartDatPtr->acRxCircularBuffer[0];
return size;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int UartTransmitData(int p_iUartHandle, char *p_pcBuffer, int p_iSize)
{
int iRet = 0;
// Case where OutPtr < InPtr
// * = Available space
//
//Top ---->|---------------|
// | * |
//OutPtr ->| |
// | |
// | (p_pcBuffer) | //Available size = (OutPtr - Top) + (Bottom - InPtr)
// | |
//InPtr -->| |
// | * |
// | * |
//Bottom ->|---------------|
// Case where OutPtr > InPtr
// * = Available space
//
//Top ---->|---------------|
// | |
//InPtr -->| |
// | * |
// | * | //available size = OutPtr - InPtr
// | * |
//OutPtr ->| |
// | (p_pcBuffer) |
// | |
//Bottom ->|---------------|
//Check if data buffer fits in remaining circular buffer space
if(astUartData[p_iUartHandle].pcTxOutPtr < astUartData[p_iUartHandle].pcTxInPtr)
{
//Calculate remaining buffer space and check if it's enough to fit requested data buffer
if(p_iSize > ((astUartData[p_iUartHandle].pcTxOutPtr - &astUartData[p_iUartHandle].acTxCircularBuffer[0]) + //Outptr - Top
(&astUartData[p_iUartHandle].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE-1] - astUartData[p_iUartHandle].pcTxInPtr))) //Bottom - Inptr
{
//Drop remaining packets, flush buffer
astUartData[p_iUartHandle].iDataPending = 0;
astUartData[p_iUartHandle].pcTxInPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0];
astUartData[p_iUartHandle].pcTxOutPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0];
return UART_BUFFER_FULL;
}
}
else if(astUartData[p_iUartHandle].pcTxInPtr < astUartData[p_iUartHandle].pcTxOutPtr)
{
//Calculate remaining buffer space and check if it's enough to fit requested data buffer
if(p_iSize > (astUartData[p_iUartHandle].pcTxOutPtr - astUartData[p_iUartHandle].pcTxInPtr))
{
//Drop remaining packets, flush buffer
astUartData[p_iUartHandle].iDataPending = 0; //Force data pending flag to flush buffer
astUartData[p_iUartHandle].pcTxInPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0];
astUartData[p_iUartHandle].pcTxOutPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0];
return UART_BUFFER_FULL;
}
}
else //OutPtr = InPtr
{
if(p_iSize > UART_MAX_TX_BUFF_SIZE - 1) //message is too big to fit in buffer !!!
{
//Drop remaining packets, flush buffer
astUartData[p_iUartHandle].iDataPending = 0; //Force data pending flag to flush buffer
astUartData[p_iUartHandle].pcTxInPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0];
astUartData[p_iUartHandle].pcTxOutPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0];
return UART_BUFFER_FULL;
}
}
int i;
for(i = 0; i < p_iSize; i++)
{
*astUartData[p_iUartHandle].pcTxInPtr++ = *p_pcBuffer++; //fill circular buffer
if(astUartData[p_iUartHandle].pcTxInPtr > &astUartData[p_iUartHandle].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE-1]) //check for wrapping
{
astUartData[p_iUartHandle].pcTxInPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0];
}
}
//Now flag pending data for transmission.
astUartData[p_iUartHandle].iDataPending = 1; //The data send will start on next Main loop processing
return iRet;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//Some data has been entirely sent
//Move output pointer
//
int DataSentNotification(int p_iUartHandle,int DataSize)
{
//Check wrapping.
if(astUartData[p_iUartHandle].pcTxOutPtr + DataSize < &astUartData[p_iUartHandle].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE])
{
astUartData[p_iUartHandle].pcTxOutPtr += DataSize;
}
else //Pointer must wrap
{
//Top ------>|---------------|
// | * |
//Final Pos->| | // Final Pos = Top + *
// | |
// | (buffer) | // DataSize = & + *
// | | // & = Bottom - OutPtr
//OutPtr --->| | // * = DataSize - &
// | & | // FinalPos = Top + (DataSize - (Bottom - OutPtr))
// | & |
//Bottom --->|---------------|
// if(p_iUartHandle != PRINTF_UART_PORT)
// printf("Out wrap\r");
DataSize -= (&astUartData[p_iUartHandle].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE] - astUartData[p_iUartHandle].pcTxOutPtr); //p_iSize - (Bottom - OutPtr)
astUartData[p_iUartHandle].pcTxOutPtr = &astUartData[p_iUartHandle].acTxCircularBuffer[0] + DataSize; //Top + new p_iSize
}
//Check if data is pending in buffer
if(astUartData[p_iUartHandle].pcTxOutPtr != astUartData[p_iUartHandle].pcTxInPtr)
{
astUartData[p_iUartHandle].iDataPending = 1;
}
else
{
astUartData[p_iUartHandle].iDataPending = 0;
LORA_MODULE_TX_LED_PIN = LED_OFF;
}
return UART_OK;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//Called by main loop. Check if any uart has data pending to be sent
//
int UartTick(void)
{
int i = 0;
int iRet;
int p_iSize;
char aTempBuffer[UART_MAX_RX_BUFF_SIZE];
TickInternalUart();
//Send...
for(i = 0; i < MAX_UART_HANDLE; i++)
{
if(astUartData[i].iDataPending)
{
char *pcTxInPtr = astUartData[i].pcTxInPtr;
//Check remaining data size.
if(astUartData[i].pcTxOutPtr < pcTxInPtr)
{
p_iSize = pcTxInPtr - astUartData[i].pcTxOutPtr;
}
else
{
p_iSize = ((&astUartData[i].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE] - astUartData[i].pcTxOutPtr) +
(pcTxInPtr - &astUartData[i].acTxCircularBuffer[0]));
}
if(astUartData[i].iIsInternal) //Uart handle mapped to PIC internal uart
{
astUartData[i].iDataPending = 0;
iRet = SendInternalUartData(astUartData[i].pcTxOutPtr,
p_iSize,
astUartData[i].iPhysicalUartPort,
&astUartData[i].acTxCircularBuffer[0],
&astUartData[i].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE-1]);
}
#ifndef NO_EXTERNAL_UART
else //mapped to external uart
{
astUartData[i].iDataPending = 0;
iRet = SendExternalUartData(astUartData[i].iPhysicalUartPort, astUartData[i].pcTxOutPtr, p_iSize,&astUartData[i].acTxCircularBuffer[0], &astUartData[i].acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE-1]);
}
#endif
//TODO: manage return values
switch(iRet)
{
case UART_OK:
{
break;
}
case UART_PORT_BUSY:
case UART_BUFFER_FULL:
{
astUartData[i].iDataPending = 1;
break;
}
case UART_PORT_NOT_OPENED:
{
break;
}
}
}
//Receive...
// int iNbPendingData = astUartData[i].iNbRxFIFOPendingBytes; //JFM 2012-09-05
int iNbPendingData = UartGetPendingDataSize(i);
if(iNbPendingData > 0)
{
int byte;
for(byte = 0; byte < iNbPendingData; byte++)
{
aTempBuffer[byte] = *astUartData[i].pcRxOutDataPtr++;
if(astUartData[i].pcRxOutDataPtr > &astUartData[i].acRxCircularBuffer[UART_MAX_RX_BUFF_SIZE-1])
astUartData[i].pcRxOutDataPtr = &astUartData[i].acRxCircularBuffer[0]; //wrap pointer
}
astUartData[i].iNbRxFIFOPendingBytes -= iNbPendingData;
switch(i)
{
// case DRIVE_UART_PORT:
// {
// //printf("drive rx\n");
// DriveProtocolRxData(aTempBuffer,iNbPendingData);
// break;
// }
// case CU_UART_PORT:
// {
// CUProtocolRxData(aTempBuffer,iNbPendingData); // HCAM 20120918
// break;
// }
case NETWORK_UART_PORT:
{
//HEARTBEAT_LED_1_TOGGLE_REG = HEARTBEAT_LED_1_TOGGLE_MASK;
//UartTransmitData(CONSOLE_UART_PORT, aTempBuffer, iNbPendingData);//echo received character
int i = 0;
for(i = 0; i< iNbPendingData; i++)
{
ProtocolAnalyzeNewData(aTempBuffer[i]);
//RxTerminalData(aTempBuffer[i]);
}
break;
}
}
}
}
return UART_OK;
}
//-----------------------------------------------------------------------------
//
// This function is used in the case of a large amount of data to be sent or received
// in a process without going back to main loop.
void UartBlockAndTick(unsigned int TickCount)
{
int i;
// KickWatchdog();
for(i = 0; i < TickCount; i++)
{
UartTick();
}
// KickWatchdog();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// This function is used in the case of a large amount of data to be sent or received
// in a process without going back to main loop.
int UartBlockUntillBufEmpty(int iUartHandle)
{
if(iUartHandle >= MAX_UART_HANDLE)
return 0;
// KickWatchdog();
while(astUartData[iUartHandle].iDataPending)
{
UartTick();
}
// KickWatchdog();
return 1;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//Overload the stdio character output routine to redirect printfs
//
//void _mon_putc(char c)
//{
// KickWatchdog();
// U2TXREG = c;
// while (U2STAbits.TRMT==0);
//#ifdef USE_BLOCKING_PRINTF
// switch(CONSOLE_UART_PORT)
// {
// case UART_1: //(422) Uart 1B
// {
// if(U1MODEbits.ON == 1)
// {
// U1TXREG = c;
// while (U1STAbits.TRMT==0);
// }
// break;
// }
// case UART_2: //(422) Uart 2A
// {
// if(U2MODEbits.ON == 1)
// {
// U2TXREG = c;
// while (U2STAbits.TRMT==0);
// }
// break;
// }
// }
//#else
// UartTransmitData(PRINTF_UART_PORT, &c, 1);
//#endif
// UartTransmitData(CONSOLE_UART_PORT, &c, 1);
// Nop();
// KickWatchdog();
//}
/*
void _mon_write (const char * s, unsigned int count)
{
#ifdef USE_BLOCKING_PRINTF
int i;
for(i = 0; i < count; i++)
_mon_putc(*s++);
#else
UartTransmitData(UART_10, s, count);
#endif
}*/
//EOF
+106
View File
@@ -0,0 +1,106 @@
/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C header file.
*/
/* ************************************************************************** */
/* ¤Revision:
000 20100616 JFM,
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
#ifndef UART_H
#define UART_H
/* ************************************************************************** */
/* Defines */
#define UART_MAX_RX_BUFF_SIZE 512
#define UART_MAX_TX_BUFF_SIZE 1024
/* ************************************************************************** */
/* Type definitions */
//Handles to the Uart ports as mapped physically on the CU board.
//in comment is the physical port assigned to each handle
//
enum eUartHandles
{
UART_1, //(232) Uart 1 - Drive
//UART_2, //(232) Uart 2 - CU
//UART_3, // !!!EXTERNAL!!! SPI daughter board...
MAX_UART_HANDLE,
INVALID_UART_HANDLE = 0xFF
};
extern const char *gUartStrings[MAX_UART_HANDLE];
enum eUartStopBits
{
UART_ONE_STOP_BIT,
UART_ONE_HALF_STOP_BIT,
UART_TWO_STOP_BITS
};
enum eUartParity
{
UART_NO_PARITY,
UART_EVEN_PARITY,
UART_ODD_PARTIY
};
typedef struct
{
int iIsInternal;
int iPhysicalUartPort;
int iDataPending; //This flag is 0 when : TxPtr == RxPtr OR Uart is transmitting.
char acTxCircularBuffer[UART_MAX_TX_BUFF_SIZE];
char *pcTxInPtr;
char *pcTxOutPtr;
char acRxCircularBuffer[UART_MAX_RX_BUFF_SIZE];
char *pcRxInDataPtr;
char *pcRxOutDataPtr;
int iNbRxFIFOPendingBytes;
}stUartData;
enum eUartReturnValues
{
UART_OK = 1,
UART_PORT_BUSY,
UART_PORT_NOT_OPENED,
UART_BUFFER_FULL,
UART_INVALID_HANDLE,
UART_INVALID_PORT
};
/* ************************************************************************** */
/* Prototypes */
int UartTransmitData(int p_iUartHandle, char *p_pcBuffer, int p_iSize);
int UartReceiveData(int p_iUartHandle, char *p_pcBuffer, int p_iSize);
int DataSentNotification(int p_iUartHandle,int p_iDataSize);
void InitUart(void);
int UartOpenComPort(int p_iUartHandle, int p_iBaudRate, int p_iNbStopBits, int p_iParityEnable);
int UartTick(void);
void UartBlockAndTick(unsigned int TickCount);
int UartBlockUntillBufEmpty(int iUartHandle);
int UartGetPendingDataSize(int iUartHandle);
int UartResetPort(int p_iUartHandle);
#endif
//EOF
+367
View File
@@ -0,0 +1,367 @@
/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C code file.
*/
/* ************************************************************************** */
/* ¤Revision:
000 20100616 JFM,
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
/* ************************************************************************** */
/* Includes */
#include "define.h"
#include "Util.h"
#include <string.h>
#include <stdio.h>
#include "PrintfServer.h"
//#include "Watchdog.h"
/* ************************************************************************** */
/* Local variables */
#ifdef ENABLE_DEBUG_LOG
char acDebugLog[DEBUG_LOG_SIZE][100];
int iLogIndex = 0;
int iWrapCntr = 0;
#endif
//void _mon_putc(char c); //override from stdio to redirect stdout
//-----------------------------------------------------------------------------
//void _mon_putc(char c)
//{
// TelnetPutPrintf(c);
//}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
short SwapEndianShort(short p_sData)
{
return (((p_sData & 0xFF00) >> 8) | ((p_sData & 0x00FF) << 8));
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int SwapEndianInt(int p_iData)
{
return (((p_iData & 0xFF000000) >> 24) | ((p_iData & 0x00FF0000) >> 8) | ((p_iData & 0x0000FF00) << 8) | ((p_iData & 0x000000FF) << 24));
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#ifdef ENABLE_DEBUG_LOG
char* GetDebugLogPtr(void)
{
char *pcPtr;
if(iLogIndex == DEBUG_LOG_SIZE)
{
iLogIndex = 0;
iWrapCntr++;
}
memset(&acDebugLog[iLogIndex][0],0,sizeof(acDebugLog[iLogIndex]));
pcPtr = &acDebugLog[iLogIndex][0];
iLogIndex++;
return pcPtr;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void ClearDebugLog(void)
{
int i;
for(i = 0; i < DEBUG_LOG_SIZE; i++)
{
memset(&acDebugLog[i][0],0,sizeof(acDebugLog[i]));
}
iLogIndex = 0;
iWrapCntr = 0;
}
#endif
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int ConvertIntToStrLeadingZero(char* p_pcString, unsigned int p_iChar, int digit)
{
char temp[8];
int i=0;
sprintf(temp, "%X", p_iChar);
//itoa(p_cChar,temp,radix);
if(p_iChar < 0xF)
{
for (i=0; i<digit-1; i++)
p_pcString[i] = '0'; //Add a Zero in front of the Character
memcpy(&p_pcString[i], &temp[0], digit-i);
}
else if(p_iChar < 0xFF)
{
for (i=0; i<digit-2; i++)
p_pcString[i] = '0'; //Add a Zero in front of the Character
memcpy(&p_pcString[i], &temp[0], digit-i);
}
else if(p_iChar < 0xFFF)
{
for (i=0; i<digit-3; i++)
p_pcString[i] = '0'; //Add a Zero in front of the Character
memcpy(&p_pcString[i], &temp[0], digit-i);
}
else if(p_iChar < 0xFFFF)
{
for (i=0; i<digit-4; i++)
p_pcString[i] = '0'; //Add a Zero in front of the Character
memcpy(&p_pcString[i], &temp[0], digit-i);
}
else if(p_iChar < 0xFFFFF)
{
for (i=0; i<digit-5; i++)
p_pcString[i] = '0'; //Add a Zero in front of the Character
memcpy(&p_pcString[i], &temp[0], digit-i);
}
else if(p_iChar < 0xFFFFFF)
{
for (i=0; i<digit-6; i++)
p_pcString[i] = '0'; //Add a Zero in front of the Character
memcpy(&p_pcString[i], &temp[0], digit-i);
}
else if(p_iChar < 0xFFFFFFF)
{
for (i=0; i<digit-7; i++)
p_pcString[i] = '0'; //Add a Zero in front of the Character
memcpy(&p_pcString[i], &temp[0], digit-i);
}
return 1;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int ConvertIntToStr(char* p_pcString, unsigned int p_iChar)
{
char temp[8];
int i=0;
sprintf(temp, "%X", p_iChar);
if(p_iChar < 0xF)
{
p_pcString[0] = temp[0];
return 1;
}
else if(p_iChar < 0xFF)
{
for (i=0; i<2; i++)
p_pcString[i] = temp[i];
return 2;
}
else if(p_iChar < 0xFFF)
{
for (i=0; i<3; i++)
p_pcString[i] = temp[i];
return 3;
}
else if(p_iChar < 0xFFFF)
{
for (i=0; i<4; i++)
p_pcString[i] = temp[i];
return 4;
}
else if(p_iChar < 0xFFFFF)
{
for (i=0; i<5; i++)
p_pcString[i] = temp[i];
return 5;
}
else if(p_iChar < 0xFFFFFF)
{
for (i=0; i<6; i++)
p_pcString[i] = temp[i];
return 6;
}
else if(p_iChar < 0xFFFFFFF)
{
for (i=0; i<7; i++)
p_pcString[i] = temp[i];
return 7;
}
else if(p_iChar < 0xFFFFFFFF)
{
for (i=0; i<8; i++)
p_pcString[i] = temp[i];
return 8;
}
return 0;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int ConvertCharToStrLeadingZero(char* p_pcString, unsigned char p_cChar, int digit)
{
char temp[2];
int i=0;
sprintf(temp, "%X", p_cChar);
//itoa(p_cChar,temp,radix);
if(p_cChar < 0xF)
{
for (i=0; i<digit-1; i++)
p_pcString[i] = '0'; //Add a Zero in front of the Character
memcpy(&p_pcString[i], &temp[0], digit-i);
}
else if(p_cChar < 0xFF)
{
for (i=0; i<digit-2; i++)
p_pcString[i] = '0'; //Add a Zero in front of the Character
memcpy(&p_pcString[i], &temp[0], digit-i);
}
return 1;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
unsigned int ConvertStrToValue(char* p_pcString, int p_iSize, int p_iRadix)
{
int i=0;
int j=0;
unsigned int uiValue = 0;
unsigned int uiFactor = 1;
if (p_iRadix == 16)
{
for (i=p_iSize-1; i>=0; i--)
{
if (i==p_iSize-1)
{
uiValue = p_pcString[i] - 0x30;
}
else
{
for (j=i; j<=p_iSize-2; j++)
uiFactor *= 16;
uiValue += (p_pcString[i] - 0x30) * uiFactor;
}
}
}
else if (p_iRadix == 10)
{
for (i=0; i<p_iSize; i++)
{
if (i==0)
uiFactor = 1;
else
{
for (j=0; j<i; j++)
uiFactor *= 10;
}
uiValue += (p_pcString[i] - 0x30) * uiFactor;
}
}
return uiValue;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int ConvertCharToStr(char* p_pcString, unsigned char p_cChar)
{
char temp[2];
sprintf(temp, "%X", p_cChar);
if(p_cChar < 0xF)
{
p_pcString[0] = temp[0];
return 1;
}
else if(p_cChar < 0xFF)
{
p_pcString[0] = temp[0];
p_pcString[1] = temp[1];
return 2;
}
return 0;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// CRC-8 table (256 bytes)
// Crc table for poly: $C7
const int CRC8_TABLE[256] = { 0, 199, 73, 142, 146, 85, 219, 28, 227, 36, 170, 109, 113, 182, 56, 255,
1, 198, 72, 143, 147, 84, 218, 29, 226, 37, 171, 108, 112, 183, 57, 254,
2, 197, 75, 140, 144, 87, 217, 30, 225, 38, 168, 111, 115, 180, 58, 253,
3, 196, 74, 141, 145, 86, 216, 31, 224, 39, 169, 110, 114, 181, 59, 252,
4, 195, 77, 138, 150, 81, 223, 24, 231, 32, 174, 105, 117, 178, 60, 251,
5, 194, 76, 139, 151, 80, 222, 25, 230, 33, 175, 104, 116, 179, 61, 250,
6, 193, 79, 136, 148, 83, 221, 26, 229, 34, 172, 107, 119, 176, 62, 249,
7, 192, 78, 137, 149, 82, 220, 27, 228, 35, 173, 106, 118, 177, 63, 248,
8, 207, 65, 134, 154, 93, 211, 20, 235, 44, 162, 101, 121, 190, 48, 247,
9, 206, 64, 135, 155, 92, 210, 21, 234, 45, 163, 100, 120, 191, 49, 246,
10, 205, 67, 132, 152, 95, 209, 22, 233, 46, 160, 103, 123, 188, 50, 245,
11, 204, 66, 133, 153, 94, 208, 23, 232, 47, 161, 102, 122, 189, 51, 244,
12, 203, 69, 130, 158, 89, 215, 16, 239, 40, 166, 97, 125, 186, 52, 243,
13, 202, 68, 131, 159, 88, 214, 17, 238, 41, 167, 96, 124, 187, 53, 242,
14, 201, 71, 128, 156, 91, 213, 18, 237, 42, 164, 99, 127, 184, 54, 241,
15, 200, 70, 129, 157, 90, 212, 19, 236, 43, 165, 98, 126, 185, 55, 240 };
//---------------------------------------------------------------------------
//
// Function: Crc8
//
// Parameter: char* message
// int number of characters in the command
//
// Descrip: calc the crc of a commans string
//
// Author: ADubreuil (12/05/06)
//
//---------------------------------------------------------------------------
int Crc8(char* answer, int length)
{
int i,crc,key;
crc = 0;
for(i=0;i<length;i++) {
key = CRC8_TABLE[crc];
crc = answer[i] ^ key;
}
return crc;
}
//---------------------------------------------------------------------------
void Delay(unsigned int count)
{
// KickWatchdog();
// while(--count);
// KickWatchdog();
}
//---------------------------------------------------------------------------
//EOF
+63
View File
@@ -0,0 +1,63 @@
/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C header file.
*/
/* ************************************************************************** */
/* Revision:
000 20100616 HCAM
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
#ifndef _INC_UTIL_H
#define _INC_UTIL_H
/* ************************************************************************** */
/* Includes */
/* ************************************************************************** */
/* Defines */
#ifdef ENABLE_DEBUG_LOG
#define DEBUG_LOG_SIZE 300
#endif
/* ************************************************************************** */
/* Type definitions */
/* ************************************************************************** */
/* Prototypes */
short SwapEndianShort(short p_sData);
int SwapEndianEndianInt(int p_iData);
#ifdef ENABLE_DEBUG_LOG
char* GetDebugLogPtr(void);
void ClearDebugLog(void);
#endif
//int AppendCharToStrLeadingZero(char* p_pcString, unsigned char p_cChar, int radix);
//int AppendLongToStrLeadingZero(char* p_pcString, int p_iChar, int radix);
int ConvertIntToStrLeadingZero(char* p_pcString, unsigned int p_iChar, int digit);
int ConvertCharToStrLeadingZero(char* p_pcString, unsigned char p_cChar, int digit);
int ConvertIntToStr(char* p_pcString, unsigned int p_iChar);
int ConvertCharToStr(char* p_pcString, unsigned char p_cChar);
unsigned int ConvertStrToValue(char* p_pcString, int p_iSize, int p_iRadix);
int Crc8(char* answer, int length);
void Delay(unsigned int count);
#endif
//EOF
+64
View File
@@ -0,0 +1,64 @@
/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C code file.
*/
/* ************************************************************************** */
/* ¤Revision:
000 20100616 JFM,
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
/* ************************************************************************** */
/* Includes */
#include "define.h"
#include "Watchdog.h"
int WatchdogTriggered = 0;
void InitWatchdog(void)
{
if(RCONbits.WDTO == 1)
{
WatchdogTriggered = 1;
printf("Watchdog was triggered\n");
}
}
void EnableWatchdog(void)
{
// WDTCONbits.ON = 1;
WDTCONSET = _WDTCON_ON_MASK;
}
void DisableWatchdog(void)
{
// WDTCONbits.ON = 0;
WDTCONCLR = _WDTCON_ON_MASK;
}
void KickWatchdog(void)
{
// WDTCONbits.WDTCLR = 1;
WDTCONSET = 0x01;
}
//EOF
+37
View File
@@ -0,0 +1,37 @@
/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*
Description:
This is a template file for standard C header file.
*/
/* ************************************************************************** */
/* Revision:
### YYYYMMDD Initial, Bug Identification
Change description.
*/
#ifndef WATCHDOG_H
#define WATCHDOG_H
void InitWatchdog(void);
void EnableWatchdog(void);
void DisableWatchdog(void);
void KickWatchdog(void);
#endif
//EOF
+785
View File
@@ -0,0 +1,785 @@
#include "WiFiCtrl.h"
#include "string.h"
#include "driver/include/nmasic.h"
#include <stdint.h>
//#include "socket/include/socket.h"
#include "define.h"
#include "Terminal.h"
#include "driver/include/m2m_periph.h"
#include "ProtocolDefs.h"
#include "BoardCfg.h"
#include "timer.h"
#include "BootloaderProtocol.h"
#include "SPI_Flash.h"
#include "FlashMapping.h"
/** IP address of host. */
uint32 gu32HostIp = 0;
/** Retry count. */
uint8 gu8RetryCount = 0;
/** TCP client socket handlers. */
static SOCKET tcp_client_socket = -1;
SOCKET TerminalSocket = -1, TerminalServerSocket = -1;
uint8 TerminalRxBuf[1024];
#ifdef USE_SYSLOG
SOCKET SyslogSocket = -1, SyslogServerSocket = -1;
uint8 SyslogRxBuf[200]; //Syslog shall not receive much data
#endif
SOCKET NetworkSocket = -1, NetworkServerSocket = -1;
uint8 NetworkRxBuf[1024];
SOCKET BootloaderSocket = -1, BootloaderServerSocket = -1;
uint8 BootloaderRxBuf[1024];
/** Receive buffer definition. */
static uint8 gau8ReceivedBuffer[MAIN_WIFI_M2M_BUFFER_SIZE] = {0};
/** Wi-Fi status variable. */
static bool gbConnectedWifi = false;
/** Get host IP status variable. */
static bool gbHostIpByName = false;
/** TCP Connection status variable. */
static bool gbTcpConnection = false;
/** Server host name. */
static char server_host_name[] = MAIN_WEATHER_SERVER_NAME;
tstrWifiInitParam param;
uint8 mac_addr[6];
uint8 u8IsMacAddrValid;
struct sockaddr_in addr_in;
uint32 mCurIPAddress;
tstrM2MIPConfig mModuleIPConfig;
bool mWiFiInitOK = false;
char mWiFiState = WIFI_MODULE_OFF_STATE; //JFM wifi module is always OFF at boot...
/**
* \brief Callback function of IP address.
*
* \param[in] hostName Domain name.
* \param[in] hostIp Server IP.
*
* \return None.
*/
static void resolve_cb(uint8 *hostName, uint32 hostIp)
{
gu32HostIp = hostIp;
gbHostIpByName = true;
printf("Host IP is %d.%d.%d.%d\r\n",
(int)IPV4_BYTE(hostIp, 0),
(int)IPV4_BYTE(hostIp, 1),
(int)IPV4_BYTE(hostIp, 2),
(int)IPV4_BYTE(hostIp, 3));
printf("Host Name is %s\r\n", hostName);
}
static void socket_cb(SOCKET sock, uint8 u8Msg, void *pvMsg)
{
/* Check for socket event on TCP socket. */
//if(sock == TerminalSocket)
{
switch(u8Msg)
{
case SOCKET_MSG_BIND:
{
tstrSocketBindMsg *pstrBind = (tstrSocketBindMsg*)pvMsg;
if(pstrBind->status == 0)
{
if(sock == TerminalServerSocket)
{
listen(TerminalServerSocket, 0);
}
else if(sock == SyslogServerSocket)
{
listen(SyslogServerSocket,0);
}
else if(sock == NetworkServerSocket)
{
listen(NetworkServerSocket,0);
}
else if(sock == BootloaderServerSocket)
{
listen(BootloaderServerSocket,0);
printf("Bootloader server started\n");
}
}
else
{
printf("Bind Failed\n");
}
break;
}
case SOCKET_MSG_LISTEN:
{
tstrSocketListenMsg *pstrListen = (tstrSocketListenMsg*)pvMsg;
if(pstrListen->status != 0)
{
printf("socket %d listen Failed. Error: %d\n",(int)sock, pstrListen->status);
break;
}
if(sock == SyslogServerSocket)
{
m2m_periph_gpio_set_val(M2M_PERIPH_GPIO3,1);
}
break;
}
case SOCKET_MSG_ACCEPT:
{
// New Socket is accepted.
tstrSocketAcceptMsg *pstrAccept = (tstrSocketAcceptMsg *)pvMsg;
if(pstrAccept->sock >= 0)
{
if(sock == TerminalServerSocket)
{
memset(TerminalRxBuf,0,sizeof(TerminalRxBuf));
// Get the accepted socket.
TerminalSocket = pstrAccept->sock;
recv(TerminalSocket, TerminalRxBuf, sizeof(TerminalRxBuf), 0);
SendTerminalData("Bienvenue au chalet!\nLe chalet parle en anglais comme Mr. Pepin\nIf you need help... type help\n\n",strlen("Bienvenue au chalet!\nLe chalet parle en anglais comme Mr. Pepin\nIf you need help... type help\n\n"));
// SendSyslogData("Terminal client connected\n",strlen("Terminal client connected\n"));
printf("Terminal client connected\n");
m2m_periph_gpio_set_val(M2M_PERIPH_GPIO4,1);
}
else if(sock == SyslogServerSocket)
{
memset(SyslogRxBuf,0,sizeof(SyslogRxBuf));
// Get the accepted socket.
SyslogSocket = pstrAccept->sock;
recv(SyslogSocket, SyslogRxBuf, sizeof(SyslogRxBuf), 0);
m2m_periph_gpio_set_val(M2M_PERIPH_GPIO4,1);
SendSyslogData("Syslog Welcome\n",strlen("Syslog Welcome\n"));
}
else if(sock == NetworkServerSocket)
{
memset(NetworkRxBuf,0,sizeof(NetworkRxBuf));
// Get the accepted socket.
NetworkSocket = pstrAccept->sock;
recv(NetworkSocket, NetworkRxBuf, sizeof(NetworkRxBuf), 0);
printf("Network client connected\n");
}
else if(sock == BootloaderServerSocket)
{
memset(BootloaderRxBuf,0,sizeof(BootloaderRxBuf));
// Get the accepted socket.
BootloaderSocket = pstrAccept->sock;
recv(BootloaderSocket, BootloaderRxBuf, sizeof(BootloaderRxBuf), 0);
printf("Bootloader client connected\n");
}
}
else
{
printf("Socket %d : Accept Failed\n", sock);
}
break;
}
case SOCKET_MSG_RECV:
{
tstrSocketRecvMsg *pstrRecvMsg = (tstrSocketRecvMsg*)pvMsg;
if((pstrRecvMsg->pu8Buffer != NULL) && (pstrRecvMsg->s16BufferSize > 0))
{
// Process the received message
if(sock == TerminalSocket)
{
//Fwd data to Terminal...
recv(TerminalSocket, TerminalRxBuf, sizeof(TerminalRxBuf), 0);
RxTerminalBuf(TerminalRxBuf, pstrRecvMsg->s16BufferSize);
}
else if(sock == SyslogSocket)
{
//Fwd data to stdin...
recv(SyslogSocket, SyslogRxBuf, sizeof(SyslogRxBuf), 0);
//Syslog shall ignore data...
}
else if(sock == NetworkSocket)
{
//Fwd data to Network...
recv(NetworkSocket, NetworkRxBuf, sizeof(NetworkRxBuf), 0);
}
else if(sock == BootloaderSocket)
{
//Fwd data to Network...
if(recv(BootloaderSocket, BootloaderRxBuf, sizeof(BootloaderRxBuf), 0) != 0)
{
char toto;
toto = 1;
}
BootloaderProtocolProtocolAnalyzeNewData(pstrRecvMsg->pu8Buffer, pstrRecvMsg->s16BufferSize);
}
}
else //Socket must be closed.
{
if(sock == TerminalSocket)
{
close(TerminalSocket);
TerminalSocket = -1;
// SendSyslogData("Terminal client disconnected\n",strlen("Terminal client disconnected\n"));
printf("Terminal client disconnected\n");
m2m_periph_gpio_set_val(M2M_PERIPH_GPIO4,0);
}
else if(sock == SyslogSocket)
{
close(SyslogSocket);
SyslogSocket = -1;
m2m_periph_gpio_set_val(M2M_PERIPH_GPIO4,0);
}
else if(sock == NetworkSocket)
{
close(NetworkSocket);
NetworkSocket = -1;
printf("Network client disconnected\n");
}
else if(sock == BootloaderSocket)
{
close(BootloaderSocket);
BootloaderSocket = -1;
printf("Bootloader client disconnected\n");
BootloaderDeactivateBootloader();
}
}
break;
}
case SOCKET_MSG_SEND:
{
if(sock == SyslogSocket)
{
}
}
}
}
}
static void set_dev_name_to_mac(uint8 *name, uint8 *mac_addr)
{
/* Name must be in the format WINC1500_00:00 */
uint16 len;
// len = m2m_strlen(name);
if (len >= 5) {
name[len - 1] = MAIN_HEX2ASCII((mac_addr[5] >> 0) & 0x0f);
name[len - 2] = MAIN_HEX2ASCII((mac_addr[5] >> 4) & 0x0f);
name[len - 4] = MAIN_HEX2ASCII((mac_addr[4] >> 0) & 0x0f);
name[len - 5] = MAIN_HEX2ASCII((mac_addr[4] >> 4) & 0x0f);
}
}
/**
* \brief Callback to get the Wi-Fi status update.
*
* \param[in] u8MsgType Type of Wi-Fi notification.
* \param[in] pvMsg A pointer to a buffer containing the notification parameters.
*
* \return None.
*/
static void wifi_cb(uint8 u8MsgType, void *pvMsg)
{
switch (u8MsgType) {
case M2M_WIFI_RESP_CON_STATE_CHANGED: {
tstrM2mWifiStateChanged *pstrWifiState = (tstrM2mWifiStateChanged *)pvMsg;
if (pstrWifiState->u8CurrState == M2M_WIFI_CONNECTED)
{
printf("Wi-Fi connected\r\n");
#ifndef USE_STATIC_IP
// m2m_wifi_request_dhcp_client();
#else
m2m_wifi_set_static_ip(&mModuleIPConfig);
gbConnectedWifi = true;
mCurIPAddress = mModuleIPConfig.u32StaticIP;
#endif
mWiFiState = WIFI_CONNECTED_STATE;
} else if (pstrWifiState->u8CurrState == M2M_WIFI_DISCONNECTED)
{
printf("Wi-Fi disconnected\r\n");
gbConnectedWifi = false;
mWiFiState = WIFI_DISCONNECTED_STATE;
CloseSockets();
m2m_periph_gpio_set_val(M2M_PERIPH_GPIO3,0);
mCurIPAddress = 0xFFFFFFFF;
}
break;
}
case M2M_WIFI_REQ_DHCP_CONF:
{
// mCurIPAddress = *(uin32*)pvMsg;
// unsigned char ip1,ip2,ip3,ip4;
// ip1 = IPV4_BYTE(pu8IPAddress,0);
// ip2 = IPV4_BYTE(pu8IPAddress,1);
// ip3 = IPV4_BYTE(pu8IPAddress,2);
// ip4 = IPV4_BYTE(pu8IPAddress,3);
/* Turn LED0 on to declare that IP address received. */
// printf("Wi-Fi IP is %u.%u.%u.%u\r\n", pu8IPAddress[0], pu8IPAddress[1], pu8IPAddress[2], pu8IPAddress[3]);
gbConnectedWifi = true;
/* Obtain the IP Address by network name */
gethostbyname((uint8 *)server_host_name);
break;
}
case M2M_WIFI_RESP_PROVISION_INFO:
{
tstrM2MProvisionInfo *pstrProvInfo = (tstrM2MProvisionInfo *)pvMsg;
printf("wifi_cb: M2M_WIFI_RESP_PROVISION_INFO.\r\n");
if (pstrProvInfo->u8Status == M2M_SUCCESS) {
m2m_wifi_connect((char *)pstrProvInfo->au8SSID,
strlen((char *)pstrProvInfo->au8SSID),
pstrProvInfo->u8SecType,
pstrProvInfo->au8Password,
M2M_WIFI_CH_ALL);
} else {
printf("wifi_cb: Provision failed.\r\n");
}
} break;
default: {
break;
}
}
}
int InitWiFi()
{
tstrWifiInitParam param;
int8_t ret;
gbTcpConnection = false;
TimerStart(WIFI_RECONNECT_TIMER,1);
mCurIPAddress = 0xFFFFFFFF;
char IP1,IP2,IP3,IP4,GW1,GW2,GW3,GW4;
if(SPIFlashIsPresent() == 1)
{
char StoredIPConfig[8];
if(SPIFlashReadBuffer(StoredIPConfig,8,FLASH_WIFI_IP_ADDRESS) != RET_ERROR)
{
IP1 = StoredIPConfig[0];
IP2 = StoredIPConfig[1];
IP3 = StoredIPConfig[2];
IP4 = StoredIPConfig[3];
GW1 = StoredIPConfig[4];
GW2 = StoredIPConfig[5];
GW3 = StoredIPConfig[6];
GW4 = StoredIPConfig[7];
if((IP1 == (char)0xFF) && (IP2 == (char)0xFF) && (IP3 == (char)0xFF) && (IP4 == (char)0xFF) || \
((GW1 == (char)0xFF && GW2 == (char)0xFF && GW3 == (char)0xFF && GW4 == (char)0xFF)))
{
IP1 = STATIC_IP_ADDRESS_1;
IP2 = STATIC_IP_ADDRESS_2;
IP3 = STATIC_IP_ADDRESS_3;
IP4 = STATIC_IP_ADDRESS_4;
GW1 = GATEWAY_ADDRESS_1;
GW2 = GATEWAY_ADDRESS_2;
GW3 = GATEWAY_ADDRESS_3;
GW4 = GATEWAY_ADDRESS_4;
}
}
}
else
{
IP1 = STATIC_IP_ADDRESS_1;
IP2 = STATIC_IP_ADDRESS_2;
IP3 = STATIC_IP_ADDRESS_3;
IP4 = STATIC_IP_ADDRESS_4;
GW1 = GATEWAY_ADDRESS_1;
GW2 = GATEWAY_ADDRESS_2;
GW3 = GATEWAY_ADDRESS_3;
GW4 = GATEWAY_ADDRESS_4;
}
memset(&mModuleIPConfig,0,sizeof(mModuleIPConfig));
// mModuleIPConfig.u32StaticIP = IP_TO_U32(STATIC_IP_ADDRESS_1,STATIC_IP_ADDRESS_2,STATIC_IP_ADDRESS_3,STATIC_IP_ADDRESS_4);
mModuleIPConfig.u32StaticIP = IP_TO_U32(IP1,IP2,IP3,IP4);
mModuleIPConfig.u32DNS = IP_TO_U32(DEFAULT_DNS_ADD_1,DEFAULT_DNS_ADD_2,DEFAULT_DNS_ADD_3,DEFAULT_DNS_ADD_4);
// mModuleIPConfig.u32AlternateDNS = IP_TO_U32(ALT_DNS_ADD_1,ALT_DNS_ADD_2,ALT_DNS_ADD_3,ALT_DNS_ADD_4);
// mModuleIPConfig.u32Gateway = IP_TO_U32(GATEWAY_ADDRESS_1,GATEWAY_ADDRESS_2,GATEWAY_ADDRESS_3,GATEWAY_ADDRESS_4);
mModuleIPConfig.u32Gateway = IP_TO_U32(GW1,GW2,GW3,GW4);
mModuleIPConfig.u32SubnetMask = IP_TO_U32(SUBNET_MASK_1,SUBNET_MASK_2,SUBNET_MASK_3,SUBNET_MASK_4);
/* Initialize the BSP. */
// nm_bsp_init();
/* Initialize Wi-Fi parameters structure. */
memset((uint8_t *)&param, 0, sizeof(tstrWifiInitParam));
/* Initialize Wi-Fi driver with data and status callbacks. */
param.pfAppWifiCb = (void*) &wifi_cb;
ret = m2m_wifi_init(&param);
if (M2M_SUCCESS != ret)
{
mWiFiInitOK = false;
mWiFiState = WIFI_INIT_ERROR_STATE;
return RET_ERROR;
}
mWiFiInitOK = true;
mWiFiState = WIFI_DISCONNECTED_STATE;
socketInit();
registerSocketCallback(socket_cb, resolve_cb);
//Get MAC address from the module
m2m_wifi_get_otp_mac_address(mac_addr, &u8IsMacAddrValid);
if (!u8IsMacAddrValid) {
m2m_wifi_set_mac_address(gau8MacAddr);
}
//Get the working MAC address from driver.
m2m_wifi_get_mac_address(gau8MacAddr);
//Initialize the human readable MAC address based on the working MAC
set_dev_name_to_mac((uint8 *)gacDeviceName, gau8MacAddr);
//Use the MAC to define the SSID of the module
set_dev_name_to_mac((uint8 *)gstrM2MAPConfig.au8SSID, gau8MacAddr);
// m2m_wifi_set_device_name((uint8 *)gacDeviceName, (uint8)m2m_strlen((uint8 *)gacDeviceName));
#ifdef USE_STATIC_IP
//Use static ip --> disable dhcp client before connecting
m2m_wifi_enable_dhcp(0);
#endif
if(m2m_wifi_connect(HOME_AP_NAME,sizeof(HOME_AP_NAME),HOME_AP_SEC_TYPE,HOME_AP_PWD,M2M_WIFI_CH_ALL) != M2M_SUCCESS)
{
//wifi connect error...
printf("error");
}
tstrPerphInitParam tst;
m2m_periph_init(&tst);
//Set all IOs as inputs except the LED (IO3)..
m2m_periph_gpio_set_dir(M2M_PERIPH_GPIO3,1);
m2m_periph_gpio_set_dir(M2M_PERIPH_GPIO4,1);
m2m_periph_gpio_set_dir(M2M_PERIPH_GPIO15,1);
m2m_periph_gpio_set_dir(M2M_PERIPH_GPIO16,0);
m2m_periph_gpio_set_dir(M2M_PERIPH_GPIO18,0);
// m2m_periph_gpio_set_dir(M2M_PERIPH_GPIO6,0);
m2m_periph_gpio_set_val(M2M_PERIPH_GPIO3,0);
m2m_periph_gpio_set_val(M2M_PERIPH_GPIO4,0);
m2m_periph_gpio_set_val(M2M_PERIPH_GPIO15,0);
m2m_periph_gpio_set_val(M2M_PERIPH_GPIO16,0);
m2m_periph_gpio_set_val(M2M_PERIPH_GPIO18,0);
// m2m_periph_gpio_set_val(M2M_PERIPH_GPIO6,0);
TimerStart(WIFI_RECONNECT_TIMER,WIFI_CONNECT_TIMEOUT);
// m2m_wifi_start_provision_mode((tstrM2MAPConfig *)&gstrM2MAPConfig, (char *)gacHttpProvDomainName, 1);
// printf("Provision Mode started.\r\nConnect to [%s] via AP[%s] and fill up the page.\r\n",
// MAIN_HTTP_PROV_SERVER_DOMAIN_NAME,
// gstrM2MAPConfig.au8SSID);
}
int TurnOFFWiFi()
{
int shit;
CloseSockets();
socketDeinit();
m2m_wifi_disconnect();
m2m_wifi_deinit(&shit);
WIFI_CHP_EN_PIN = 0;
WIFI_CHP_RST_PIN = 0;
mWiFiInitOK = false;
gbConnectedWifi = false;
HEARTBEAT_LED_2_PIN = LED_OFF;
// WIFI
mWiFiState = WIFI_MODULE_OFF_STATE;
return RET_OK;
}
int CloseSockets()
{
gbTcpConnection = false;
close(TerminalServerSocket);
if(TerminalSocket != -1)
{
close(TerminalSocket);
}
close(NetworkServerSocket);
if(NetworkSocket != -1)
{
close(NetworkSocket);
}
#ifdef USE_SYSLOG
close(SyslogServerSocket);
if(SyslogSocket != -1)
{
close(SyslogSocket);
}
#endif
close(BootloaderServerSocket);
if(BootloaderSocket != -1)
{
close(BootloaderSocket);
}
}
char GetWiFiSate()
{
return mWiFiState;
}
void TickWiFi()
{
if(mWiFiInitOK == false)
{
return;
}
if(mWiFiState == WIFI_DISCONNECTED_STATE && gbConnectedWifi == false)//we should be connected.. if the timer is expired, retry
{
if(IsTimerExpired(WIFI_RECONNECT_TIMER))
{
//m2m_wifi_disconnect();
m2m_wifi_connect(HOME_AP_NAME,sizeof(HOME_AP_NAME),HOME_AP_SEC_TYPE,HOME_AP_PWD,M2M_WIFI_CH_ALL);
TimerStart(WIFI_RECONNECT_TIMER,WIFI_CONNECT_TIMEOUT);
}
}
// if(IsTimerExpired(WIFI_TICK_TIMER))
// {
m2m_wifi_handle_events();
// TimerStart(WIFI_TICK_TIMER,1);
// }
if (gbConnectedWifi && !gbTcpConnection)
{
OpenTerminalServer();
//OpenNetworkServer();
// OpenBootloaderServer();
// BootloaderActivateBootloader();
#ifdef USE_SYSLOG
OpenSyslogServer();
#endif
gbTcpConnection = true;
}
}
//Terminal server implementation
int OpenTerminalServer()
{
struct sockaddr_in strAddr;
TerminalServerSocket = socket(AF_INET, SOCK_STREAM,0);
uint16 TerminalPort = TERMINAL_SERVER_PORT;
if(TerminalServerSocket >= 0)
{
strAddr.sin_family = AF_INET;
strAddr.sin_port = _htons(TerminalPort);
strAddr.sin_addr.s_addr = 0;
bind(TerminalServerSocket, (struct sockaddr*)&strAddr, sizeof(struct sockaddr_in));
return RET_OK;
}
else
{
return RET_ERROR;
}
}
void SendTerminalData(uint8 *data, int size)
{
if(TerminalSocket != -1)
{
send(TerminalSocket,data,size,0);
recv(TerminalSocket,TerminalRxBuf,sizeof(TerminalRxBuf),0);
}
}
void SentTerminalByte(uint8 data)
{
if(TerminalSocket != -1)
{
send(TerminalSocket,&data,1,0);
recv(TerminalSocket,TerminalRxBuf,sizeof(TerminalRxBuf),0);
}
}
int OpenNetworkServer()
{
struct sockaddr_in strAddr;
NetworkServerSocket = socket(AF_INET, SOCK_STREAM,0);
uint16 ServerPort = NETWORK_SERVER_PORT;
if(NetworkServerSocket >= 0)
{
strAddr.sin_family = AF_INET;
strAddr.sin_port = _htons(ServerPort);
strAddr.sin_addr.s_addr = 0;
bind(NetworkServerSocket, (struct sockaddr*)&strAddr, sizeof(struct sockaddr_in));
return RET_OK;
}
else
{
return RET_ERROR;
}
}
void SendNetworkData(uint8 *data, int size)
{
if(NetworkSocket != -1)
{
send(NetworkSocket,data,size,0);
recv(NetworkSocket,TerminalRxBuf,sizeof(TerminalRxBuf),0);
}
}
void SentNetworkByte(uint8 data)
{
if(NetworkSocket != -1)
{
send(NetworkSocket,&data,1,0);
recv(NetworkSocket,TerminalRxBuf,sizeof(TerminalRxBuf),0);
}
}
//Printf Server Implementation
#ifdef USE_SYSLOG
int OpenSyslogServer()
{
struct sockaddr_in strAddr;
SyslogServerSocket = socket(AF_INET, SOCK_STREAM,0);
uint16 ServerPort = SYSLOG_SERVER_PORT;
if(SyslogServerSocket >= 0)
{
strAddr.sin_family = AF_INET;
strAddr.sin_port = _htons(ServerPort);
strAddr.sin_addr.s_addr = 0;
bind(SyslogServerSocket, (struct sockaddr*)&strAddr, sizeof(struct sockaddr_in));
return RET_OK;
}
else
{
return RET_ERROR;
}
}
void SendSyslogData(uint8 *data, int size)
{
if(SyslogSocket != -1);
{
send(SyslogSocket,data,size,0);
recv(SyslogSocket,SyslogRxBuf,sizeof(SyslogRxBuf),0);
}
}
void SendSyslogByte(uint8 data)
{
if(SyslogSocket != -1)
{
send(SyslogSocket,&data,1,0);
recv(SyslogSocket,SyslogRxBuf,sizeof(SyslogRxBuf),0);
}
}
int IsSyslogClientConnected()
{
if(SyslogSocket == -1)
{
return 0;
}
return 1;
}
#endif
int OpenBootloaderServer()
{
struct sockaddr_in strAddr;
BootloaderServerSocket = socket(AF_INET, SOCK_STREAM,0);
uint16 ServerPort = BOOTLOADER_SERVER_PORT;
if(BootloaderServerSocket >= 0)
{
strAddr.sin_family = AF_INET;
strAddr.sin_port = _htons(ServerPort);
strAddr.sin_addr.s_addr = 0;
bind(BootloaderServerSocket, (struct sockaddr*)&strAddr, sizeof(struct sockaddr_in));
return RET_OK;
}
else
{
return RET_ERROR;
}
}
int CloseBootloaderServer()
{
close(BootloaderServerSocket);
BootloaderServerSocket = -1;
if(BootloaderSocket != -1)
{
close(BootloaderSocket);
BootloaderSocket = -1;
}
}
void SendBootloaderData(uint8 *data, int size)
{
if(BootloaderSocket != -1);
{
send(BootloaderSocket,data,size,0);
recv(BootloaderSocket,SyslogRxBuf,sizeof(SyslogRxBuf),0);
}
}
void SendSBootloaderByte(uint8 data)
{
if(BootloaderSocket != -1)
{
send(BootloaderSocket,&data,1,0);
recv(BootloaderSocket,SyslogRxBuf,sizeof(SyslogRxBuf),0);
}
}
int IsBootloaderClientConnected()
{
if(BootloaderSocket == -1)
{
return 0;
}
return 1;
}
+137
View File
@@ -0,0 +1,264 @@
/*
* File: WiFiCtrl.h
* Author: JF
*
* Created on December 8, 2018, 6:52 AM
*/
#ifndef WIFICTRL_H
#define WIFICTRL_H
#include "driver/include/m2m_wifi.h"
#include "socket/include/socket.h"
/*!
* Used for code portability.
*/
/*!
* @typedef void (*tpfNmBspIsr) (void);
* @brief Pointer to function.\n
* Used as a data type of ISR function registered by \ref nm_bsp_register_isr
* @return None
*/
typedef void (*tpfNmBspIsr)(void);
/*!
* @ingroup DataTypes
* @typedef unsigned char uint8;
* @brief Range of values between 0 to 255
*/
typedef unsigned char uint8;
/*!
* @ingroup DataTypes
* @typedef unsigned short uint16;
* @brief Range of values between 0 to 65535
*/
typedef unsigned short uint16;
/*!
* @ingroup Data Types
* @typedef unsigned long uint32;
* @brief Range of values between 0 to 4294967295
*/
typedef unsigned long uint32;
/*!
* @ingroup Data Types
* @typedef signed char sint8;
* @brief Range of values between -128 to 127
*/
typedef signed char sint8;
/*!
* @ingroup DataTypes
* @typedef signed short sint16;
* @brief Range of values between -32768 to 32767
*/
typedef signed short sint16;
/*!
* @ingroup DataTypes
* @typedef signed long sint32;
* @brief Range of values between -2147483648 to 2147483647
*/
typedef signed long sint32;
//@}
int InitWiFi();
void TickWiFi();
int TurnOFFWiFi();
int CloseSockets();
char GetWiFiSate();
int OpenTerminalServer();
void SendTerminalData(uint8 *data, int size);
void SentTerminalByte(uint8 data);
int OpenNetworkServer();
void SendNetworkData(uint8 *data, int size);
void SentNetworkByte(uint8 data);
int OpenSyslogServer();
void SendSyslogData(uint8 *data, int size);
void SendSyslogByte(uint8 data);
int IsSyslogClientConnected();
int OpenBootloaderServer();
int CloseBootloaderServer();
void SendBootloaderData(uint8 *data, int size);
void SendBootloaderByte(uint8 data);
int IsBootloaderClientConnected();
//#define USE_STATIC_IP
// <<< Use Configuration Wizard in Context Menu >>>
//<h> General network settings in AP (access point) mode
// <s> Network SSID
// <id> app_main_m2m_device_name
#ifndef MAIN_M2M_SSID
#define MAIN_M2M_SSID "WINC3400_00:00"
#endif
// <o> Security type
// <1=> Wi-Fi network is not secured
// <2=> WPA/WPA2 personal(PSK)
// <3=> WEP (40 or 104) OPEN OR SHARED
// <4=> WPA/WPA2 Enterprise.IEEE802.1x
// <id> app_main_m2m_ap_sec
#ifndef MAIN_M2M_AP_SEC
#define MAIN_M2M_AP_SEC 1
#endif
// <s> Security key
// <id> app_main_m2m_ap_key
#ifndef MAIN_M2M_AP_KEY
#define MAIN_M2M_AP_KEY "12345FFFFF"
#endif
// <o> SSID mode
// <0=>SSID is visible to others
// <1=>SSID is hidden
// <id> app_main_m2m_ap_ssid_mode
#ifndef MAIN_M2M_AP_SSID_MODE
#define MAIN_M2M_AP_SSID_MODE 0
#endif
//</h>
//<h> DHCP server IP address in AP (access point) mode
// <o> DHCP serv