First commit

This commit is contained in:
jfmartel 2022-04-27 16:08:20 -04:00
commit 561a8479b7
270 changed files with 158521 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.o
*.d

113
ChaloupeLora.X/Makefile Normal file
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
ChaloupeLora.X/Source/ADC.c Normal file
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

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

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;
}

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 */

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 */

View File

@ -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 */

View File

@ -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 */

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 */

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 */

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;
}

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 */

View File

@ -0,0 +1,427 @@
/**********************************************************************
Project: Automatic cat feeder
Date: march 19 2006
Author: Jean-Fran<EFBFBD>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);
}

View File

@ -0,0 +1,123 @@
/**********************************************************************
Project: Automatic cat feeder
Date: march 19 2006
Author: Jean-Fran<EFBFBD>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

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;
}

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 */

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;
}

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;
}

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();
}

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 */

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

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

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;
}

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

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 */

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 ---*/

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

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

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;
}

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 */

View File

@ -0,0 +1,6 @@
#include "BoardCfg.h"
int InitBoard()
{
return RET_OK;
}

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;
}

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
ChaloupeLora.X/Source/I2C.c Normal file
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;
}

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 */

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

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

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;
}
}
}

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 */

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;
}

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 */

View File

@ -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);
}

View File

@ -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 */

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);
}

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 */

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;
}

View File

@ -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 */

View File

@ -0,0 +1,324 @@
/**********************************************************************
Project: Automatic cat feeder
Date: march 19 2006
Author: Jean-Fran<EFBFBD>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];
}

View File

@ -0,0 +1,77 @@
/**********************************************************************
Project: Automatic cat feeder
Date: march 19 2006
Author: Jean-Fran<EFBFBD>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

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;
}

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 */

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;
}

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);
}

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

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

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

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 */

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;
}

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 */

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;
}

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 */

View File

@ -0,0 +1,7 @@
#include "define.h"
#include "Schedule.h"
void InitSchedule()
{
}

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 */

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

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

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;
}

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

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;
}

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 */

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
}

View File

@ -0,0 +1,11 @@
#ifndef TCPSERVER_H
#define TCPSERVER_H
int OpenTCPServer();
void TickTCPServer();
#endif

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);
}
}

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 */

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

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

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

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

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

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

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

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

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;
}

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 server IP address 1 <0-255>
// <id> app_ip_address_1
#ifndef DHCP_IP_ADDRESS_1
#define DHCP_IP_ADDRESS_1 192
#endif
// <o> DHCP server IP address 2 <0-255>
// <id> app_ip_address_2
#ifndef DHCP_IP_ADDRESS_2
#define DHCP_IP_ADDRESS_2 168
#endif
// <o> DHCP server IP address 3 <0-255>
// <id> app_ip_address_3
#ifndef DHCP_IP_ADDRESS_3
#define DHCP_IP_ADDRESS_3 50
#endif
// <o> DHCP server IP address 4 <0-255>
// <id> app_ip_address_4
#ifndef DHCP_IP_ADDRESS_4
#define DHCP_IP_ADDRESS_4 1
#endif
//</h>
// <<< end of configuration section >>>
//Acces Point settings
#define HOME_AP_SEC_TYPE M2M_WIFI_SEC_WPA_PSK
//#define HOME_AP_NAME "ImprVEmard"
//#define HOME_AP_PWD "12345fffff"
#define HOME_AP_NAME "ChaletVilleEmard"
//#define HOME_AP_NAME "ElRouteurDuChalet"
//#define HOME_AP_NAME "LeChalet"
#define HOME_AP_PWD "Evinrude30"
#define TERMINAL_SERVER_PORT 85
#define NETWORK_SERVER_PORT 86
#define SYSLOG_SERVER_PORT 87
#define BOOTLOADER_SERVER_PORT 99
#define AUTH_CREDENTIALS {M2M_802_1X_USR_NAME, M2M_802_1X_PWD }
//Module Static IP settings
#define STATIC_IP_ADDRESS_1 192
#define STATIC_IP_ADDRESS_2 168
#define STATIC_IP_ADDRESS_3 30
#define STATIC_IP_ADDRESS_4 127
#define GATEWAY_ADDRESS_1 192
#define GATEWAY_ADDRESS_2 168
#define GATEWAY_ADDRESS_3 30
#define GATEWAY_ADDRESS_4 1
#define DEFAULT_DNS_ADD_1 8
#define DEFAULT_DNS_ADD_2 8
#define DEFAULT_DNS_ADD_3 8
#define DEFAULT_DNS_ADD_4 8
#define ALT_DNS_ADD_1 8
#define ALT_DNS_ADD_2 8
#define ALT_DNS_ADD_3 4
#define ALT_DNS_ADD_4 4
#define SUBNET_MASK_1 255
#define SUBNET_MASK_2 255
#define SUBNET_MASK_3 255
#define SUBNET_MASK_4 0
#define IP_TO_U32(add1,add2,add3,add4) (((add4<<24)&0xFF000000) | ((add3<<16)&0x00FF0000) | ((add2<<8)&0x0000FF00) | (add1&0x000000FF))
/** Using broadcast address for simplicity. */
#define MAIN_SERVER_PORT (80)
/** Using IP address. */
#define IPV4_BYTE(val, index) ((val >> (index * 8)) & 0xFF)
/** Send buffer of TCP socket. */
#define MAIN_PREFIX_BUFFER "GET /data/2.5/weather?q="
#define MAIN_POST_BUFFER \
"&mode=xml&units=metric&appid=c592e14137c3471fa9627b44f6649db4 HTTP/1.1\r\nHost: " \
"api.openweathermap.org\r\nAccept: */*\r\n\r\n"
/** Weather information provider server. */
#define MAIN_WEATHER_SERVER_NAME "openweathermap.org"
/** Input City Name. */
#define MAIN_CITY_NAME "london"
/** Receive buffer size. */
#define MAIN_WIFI_M2M_BUFFER_SIZE 1024
#define MAIN_M2M_DHCP_SERVER_IP \
{ \
DHCP_IP_ADDRESS_1, DHCP_IP_ADDRESS_2, DHCP_IP_ADDRESS_3, DHCP_IP_ADDRESS_4 \
}
#define MAIN_HTTP_PROV_SERVER_DOMAIN_NAME "JF.com"
#define MAIN_MAC_ADDRESS \
{ \
0xf8, 0xf0, 0x05, 0x45, 0xD4, 0x84 \
}
#define MAIN_HEX2ASCII(x) (((x) >= 10) ? (((x)-10) + 'A') : ((x) + '0'))
#define TEMPERATURE_ABS(a) (((a) > 0) ? (a) : -(a))
static tstrM2MAPConfig gstrM2MAPConfig = {MAIN_M2M_SSID,
1,
0,
sizeof(MAIN_M2M_AP_KEY) - 1,
MAIN_M2M_AP_KEY,
MAIN_M2M_AP_SEC,
MAIN_M2M_AP_SSID_MODE,
MAIN_M2M_DHCP_SERVER_IP};
static const char gacHttpProvDomainName[] = MAIN_HTTP_PROV_SERVER_DOMAIN_NAME;
static uint8 gau8MacAddr[] = MAIN_MAC_ADDRESS;
static sint8 gacDeviceName[] = MAIN_M2M_SSID;
#define MAIN_WAITING_TIME 3000
#define MAIN_RETRY_COUNT 10
extern SOCKET TerminalSocket;
#endif /* WIFICTRL_H */

View File

@ -0,0 +1,94 @@
/*
* Library: libcrc
* File: include/checksum.h
* Author: Lammert Bies
*
* This file is licensed under the MIT License as stated below
*
* Copyright (c) 1999-2016 Lammert Bies
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Description
* -----------
* The headerfile include/checksum.h contains the definitions and prototypes
* for routines that can be used to calculate several kinds of checksums.
*/
#ifndef DEF_LIBCRC_CHECKSUM_H
#define DEF_LIBCRC_CHECKSUM_H
#include <stdint.h>
/*
* #define CRC_POLY_xxxx
*
* The constants of the form CRC_POLY_xxxx define the polynomials for some well
* known CRC calculations.
*/
#define CRC_POLY_16 0xA001
#define CRC_POLY_32 0xEDB88320L
#define CRC_POLY_CCITT 0x1021
#define CRC_POLY_DNP 0xA6BC
#define CRC_POLY_KERMIT 0x8408
#define CRC_POLY_SICK 0x8005
/*
* #define CRC_START_xxxx
*
* The constants of the form CRC_START_xxxx define the values that are used for
* initialization of a CRC value for common used calculation methods.
*/
#define CRC_START_8 0x00
#define CRC_START_16 0x0000
#define CRC_START_MODBUS 0xFFFF
#define CRC_START_XMODEM 0x0000
#define CRC_START_CCITT_1D0F 0x1D0F
#define CRC_START_CCITT_FFFF 0xFFFF
#define CRC_START_KERMIT 0x0000
#define CRC_START_SICK 0x0000
#define CRC_START_DNP 0x0000
#define CRC_START_32 0xFFFFFFFFL
/*
* Prototype list of global functions
*/
unsigned char * checksum_NMEA( const unsigned char *input_str, unsigned char *result );
uint8_t crc_8( const unsigned char *input_str, size_t num_bytes );
uint16_t crc_16( const unsigned char *input_str, size_t num_bytes );
uint32_t crc_32( const unsigned char *input_str, size_t num_bytes );
uint16_t crc_ccitt_1d0f( const unsigned char *input_str, size_t num_bytes );
uint16_t crc_ccitt_ffff( const unsigned char *input_str, size_t num_bytes );
uint16_t crc_dnp( const unsigned char *input_str, size_t num_bytes );
uint16_t crc_kermit( const unsigned char *input_str, size_t num_bytes );
uint16_t crc_modbus( const unsigned char *input_str, size_t num_bytes );
uint16_t crc_sick( const unsigned char *input_str, size_t num_bytes );
uint16_t crc_xmodem( const unsigned char *input_str, size_t num_bytes );
uint8_t update_crc_8( uint8_t crc, unsigned char c );
uint16_t update_crc_16( uint16_t crc, unsigned char c );
uint32_t update_crc_32( uint32_t crc, unsigned char c );
uint16_t update_crc_ccitt( uint16_t crc, unsigned char c );
uint16_t update_crc_dnp( uint16_t crc, unsigned char c );
uint16_t update_crc_kermit( uint16_t crc, unsigned char c );
uint16_t update_crc_sick( uint16_t crc, unsigned char c, unsigned char prev_byte );
#endif // DEF_LIBCRC_CHECKSUM_H

View File

@ -0,0 +1,131 @@
/*
* Library: libcrc
* File: src/crc32.c
* Author: Lammert Bies
*
* This file is licensed under the MIT License as stated below
*
* Copyright (c) 1999-2016 Lammert Bies
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Description
* -----------
* The source file src/crc32.c contains the routines which are needed to
* calculate a 32 bit CRC value of a sequence of bytes.
*/
#include <stdbool.h>
#include <stdlib.h>
#include "checksum.h"
static void init_crc32_tab( void );
static bool crc_tab32_init = false;
static uint32_t crc_tab32[256];
/*
* uint32_t crc_32( const unsigned char *input_str, size_t num_bytes );
*
* The function crc_32() calculates in one pass the common 32 bit CRC value for
* a byte string that is passed to the function together with a parameter
* indicating the length.
*/
uint32_t crc_32( const unsigned char *input_str, size_t num_bytes ) {
uint32_t crc;
uint32_t tmp;
uint32_t long_c;
const unsigned char *ptr;
size_t a;
if ( ! crc_tab32_init ) init_crc32_tab();
crc = CRC_START_32;
ptr = input_str;
if ( ptr != NULL ) for (a=0; a<num_bytes; a++) {
long_c = 0x000000FFL & (uint32_t) *ptr;
tmp = crc ^ long_c;
crc = (crc >> 8) ^ crc_tab32[ tmp & 0xff ];
ptr++;
}
crc ^= 0xffffffffL;
return crc & 0xffffffffL;
} /* crc_32 */
/*
* uint32_t update_crc_32( uint32_t crc, unsigned char c );
*
* The function update_crc_32() calculates a new CRC-32 value based on the
* previous value of the CRC and the next byte of the data to be checked.
*/
uint32_t update_crc_32( uint32_t crc, unsigned char c ) {
uint32_t tmp;
uint32_t long_c;
long_c = 0x000000ffL & (uint32_t) c;
if ( ! crc_tab32_init ) init_crc32_tab();
tmp = crc ^ long_c;
crc = (crc >> 8) ^ crc_tab32[ tmp & 0xff ];
return crc & 0xffffffffL;;
} /* update_crc_32 */
/*
* static void init_crc32_tab( void );
*
* For optimal speed, the CRC32 calculation uses a table with pre-calculated
* bit patterns which are used in the XOR operations in the program. This table
* is generated once, the first time the CRC update routine is called.
*/
static void init_crc32_tab( void ) {
uint32_t i;
uint32_t j;
uint32_t crc;
for (i=0; i<256; i++) {
crc = i;
for (j=0; j<8; j++) {
if ( crc & 0x00000001L ) crc = ( crc >> 1 ) ^ CRC_POLY_32;
else crc = crc >> 1;
}
crc_tab32[i] = crc;
}
crc_tab32_init = true;
} /* init_crc32_tab */

View File

@ -0,0 +1,253 @@
/*******************************************************************************
* *
* 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. *
* *
*******************************************************************************/
/* ¤Revision:
000 20100616 HCAM,
Original version.
,----.. ,----..
/ / \ / / \ ,--,
| : : __ ,-. ,---. | : : ,--.'| ,---,
. | ;. / ,' ,'/ /| ' ,'\ .--.--. . | ;. / | |, ,-+-. / |
. ; /--` ' | |' | / / | / / ' . ; /--` `--'_ ,--.'|' |
; | ; __ | | ,'. ; ,. :| : /`./ ; | ; __ ,' ,'| | | ,"' |
| : |.' .'' : / ' | |: :| : ;_ | : |.' .'' | | | | / | |
. | '_.' :| | ' ' | .; : \ \ `. . | '_.' :| | : | | | | |
' ; : \ |; : | | : | `----. \ ' ; : \ |' : |__ | | | |/
' | '/ .'| , ; \ \ / / /`--' / ' | '/ .'| | '.'|| | |--'
| : / ---' `----' '--'. / | : / ; : ;| |/
\ \ .' `--'---' \ \ .' | , / '---'
`---` `---` ---`-'
### YYYYMMDD Initial, Bug Identification
Change description.
*/
/****************************** NOTES ***************************************
-> Timers assignment <-
- Timer1 used by TCP Stack (tick.c)
- Timer2 used by general timer module (timer.c) (see GP_TIMER_USE_TIMER_X definition below)
- timer3 used by input capture to detect PWM
- timer4 used by hall acquisition module (HallAcquisition.c)
- timer5 used by FPGAInterface to time-base SPI the transfer to the FPGA
-> Interrupt priority assignment <-
Priority.SubPriority - Assignment
HIGHEST
7.3
7.2
7.1
7.0
6.3
6.2
6.1
6.0
5.3
5.2
5.1
5.0
4.3
4.2
4.1
4.0
3.3
3.2
3.1
3.0 - Wifi chip IRQ (Ext INT 0)
2.3 - TIMER2 (General purpose timer)
2.2
2.1 - Ext Interrupt 1 (Led dimming knob) NOT USED!!!
1.0
1.3
1.2
1.1
1.0
LOWEST
*****************************************************************************/
#ifndef DEFINE_H
#define DEFINE_H
/* ************************************************************************** */
/* Includes */
#include <plib.h>
//#include "CUHelperFcns.h"
enum eWiFiState
{
WIFI_MODULE_OFF_STATE = 0,
WIFI_CONNECTED_STATE,
WIFI_DISCONNECTED_STATE,
WIFI_INIT_ERROR_STATE,
WIFI_UNKNOWN_STATE
};
#define WIFI_MODULE_SPI_BAUDRATE 15000000
#define WIFI_CONNECT_TIMEOUT 10000 //The delay we allow the module to establish a connection.
/* ************************************************************************** */
/* Defines */
#define PIN_INPUT 1
#define PIN_OUTPUT 0
#define LED_ON 0
#define LED_OFF 1
#define false 0
#define true 1
#define MSB8(x) ((x >> 8) & 0xFF)
#define LSB8(x) (x & 0xFF)
#define RET_OK true
#define RET_ERROR false
#define bool unsigned int
#define PI 3.1415926536
//#define ENABLE_DEBUG_LOG
#ifdef ENABLE_DEBUG_LOG
#include "util.h"
#endif
////#define USE_HALL_ACQ_SIMULATOR //Use this switch for development to test hall acquisition traces
//#define USE_ENGINEERING_MODE //Use this switch to disable speed, position and halls traces and traces buffer allocation (all traces !)
////#define USE_TRACE_SIMULATOR //Use this switch to simulate trace data for development
////#define USE_SPI_DONGLE_SIMULATOR //Use this switch if you use the CUMUX as a SPI dongle instead of the CS16IS74 dongle.
////#define USE_PMP_AUTOINCREMENT //Use to speed-up AD2S data transfer
////#define USE_PWM_DETECTION //Use PWM detection to enable/disable bridge
////#define USE_AUTO_BRIDGE_CONTROL //Execute drive bridge control
////#define FORCE_BRIDGE_ON
////#define DRIVE_BOARD_NOT_INSTALLED
//#define DISABLE_PRINT_FAULT
//#define SPI_FAST
////#define USE_DMA_WITH_PMP
////#define USE_RESOLVER_STATEMACHINE
////#define DISABLE_DRIVE_PARAM_MGMT // uncomment to avoid setting the drive at power-up
#define NO_EXTERNAL_UART
//Choose which timer to use for general purpose timer
#define GP_TIMER_USE_TIMER_1
//#define POLL_UART1_RX
//#define POLL_UART2_RX
//#define NO_WIFI
//Define the com port assignations
//----------------------------
#define NETWORK_UART_PORT UART_1
#ifndef NO_WIFI
#define WIFI_MODULE_UART_PORT UART_2
#endif
//
//----------------------------
//Enable only one of those 3 options
//#define USE_BLOCKING_PRINTF
//#define USE_UART_PRINTF
#define USE_SYSLOG
#ifdef USE_UART_PRINTF
#ifdef USE_SYSLOG
#error "USE_UART_PRINTF and USE_SYSLOG defined simultaneously"
#endif
#endif
//#error test
#ifdef USE_SYSLOG
#ifdef NO_WIFI
#undef USE_SYSLOG
#error "USE_SYSLOG defined with NO_WIFI"
#endif
#endif
#ifdef USE_UART_PRINTF
#define PRINTF(n, a...) printf(n, ## a)
#elif defined USE_SYSLOG
#define PRINTF(n, a...) printf(n, ## a)
#else
#define PRINTF(n, a...)
#endif
#ifndef NO_WIFI
// #define USE_WIFI_PRINTF
#endif
//#define USE_UART_PRINTF
//#else
//
// #define NO_EXTERNAL_UART
//#endif
//#define CONNECT_DEVICE_TO_NETWORK
//#define TERMINAL_USE_TELNET
//#define TERMINAL_USE_TCP_SERVER
/* ************************************************************************** */
/* Type definitions */
//----- STDINT.H TYPE DEFINITIONS -----
//(Valid for XC16 & XC32 microchip PIC compilers)
#ifndef uint8_t
typedef unsigned char uint8_t;
#endif
#ifndef int8_t
typedef signed char int8_t;
#endif
#ifndef uint16_t
typedef unsigned short uint16_t;
#endif
#ifndef int16_t
typedef signed short int16_t;
#endif
/*
#ifndef uint32_t
typedef unsigned long uint32_t;
#endif
#ifndef int32_t
typedef signed long int32_t;
#endif
*/
#ifndef uint64_t
typedef unsigned long long uint64_t;
#endif
#ifndef int64_t
typedef signed long long int64_t;
#endif
#endif
//EOF

View File

@ -0,0 +1,168 @@
/*******************************************************************************
* *
* 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. *
* *
*******************************************************************************/
/* ¤Revision:
000 20100616 HCAM,
Original version.
,----.. ,----..
/ / \ / / \ ,--,
| : : __ ,-. ,---. | : : ,--.'| ,---,
. | ;. / ,' ,'/ /| ' ,'\ .--.--. . | ;. / | |, ,-+-. / |
. ; /--` ' | |' | / / | / / ' . ; /--` `--'_ ,--.'|' |
; | ; __ | | ,'. ; ,. :| : /`./ ; | ; __ ,' ,'| | | ,"' |
| : |.' .'' : / ' | |: :| : ;_ | : |.' .'' | | | | / | |
. | '_.' :| | ' ' | .; : \ \ `. . | '_.' :| | : | | | | |
' ; : \ |; : | | : | `----. \ ' ; : \ |' : |__ | | | |/
' | '/ .'| , ; \ \ / / /`--' / ' | '/ .'| | '.'|| | |--'
| : / ---' `----' '--'. / | : / ; : ;| |/
\ \ .' `--'---' \ \ .' | , / '---'
`---` `---` ---`-'
### YYYYMMDD Initial, Bug Identification
Change description.
*/
/****************************** NOTES ***************************************
-> Timers assignment <-
- Timer1 used by general timer module (timer.c)
- Timer2 used by time based Resolver data acquisition module (resolver.c)
- timer3 used by input capture to detect PWM
- timer4 used by hall acquisition module (HallAcquisition.c)
- timer5 used by FPGAInterface to time-base SPI the transfer to the FPGA
-> Interrupt priority assignment <-
Priority.SubPriority - Assignment
HIGHEST
7.3
7.2
7.1 - UART1
7.0 - UART2
6.3 - TIMER2 (Resolver acquisition & halls computation)
6.2 - PMP
6.1
6.0 - Input Capture
5.3 - ADC
5.2 - SPI
5.1
5.0
4.3 - Drive Enable pin interrupt
4.2 - AD2S DOS Pin
4.1 - AD2S LOT Pin
4.0
3.3
3.2
3.1
3.0 - TIMER5 (FPGA TX)
2.3 - TIMER1 (General purpose timer)
2.2 - TIMER3 (PWM Detection)
2.1
1.0
1.3
1.2
1.1
1.0
LOWEST
*****************************************************************************/
#ifndef DEFINE_H
#define DEFINE_H
/* ************************************************************************** */
/* Includes */
#include <plib.h>
//#include "CUHelperFcns.h"
/* ************************************************************************** */
/* Defines */
#define SYS_FREQ (77824000L) //Clock period = 12.85 ns
#define PERIPHERAL_FREQ (77824000L)
#define PIN_INPUT 1
#define PIN_OUTPUT 0
#define LED_ON 0
#define LED_OFF 1
#define false 0
#define true 1
#define MSB8(x) ((x >> 8) & 0xFF)
#define LSB8(x) (x & 0xFF)
#define PI 3.1415926536
//#define ENABLE_DEBUG_LOG
#ifdef ENABLE_DEBUG_LOG
#include "util.h"
#endif
//#define USE_HALL_ACQ_SIMULATOR //Use this switch for development to test hall acquisition traces
#define USE_ENGINEERING_MODE //Use this switch to disable speed, position and halls traces and traces buffer allocation (all traces !)
//#define USE_TRACE_SIMULATOR //Use this switch to simulate trace data for development
//#define USE_SPI_DONGLE_SIMULATOR //Use this switch if you use the CUMUX as a SPI dongle instead of the CS16IS74 dongle.
//#define USE_PMP_AUTOINCREMENT //Use to speed-up AD2S data transfer
#define USE_PWM_DETECTION //Use PWM detection to enable/disable bridge
#define USE_AUTO_BRIDGE_CONTROL //Execute drive bridge control
//#define FORCE_BRIDGE_ON
//#define DRIVE_BOARD_NOT_INSTALLED
#define DISABLE_PRINT_FAULT
#define SPI_FAST
//#define USE_DMA_WITH_PMP
//#define USE_RESOLVER_STATEMACHINE
//#define DISABLE_DRIVE_PARAM_MGMT // uncomment to avoid setting the drive at power-up
#define POLL_UART1_RX
#define POLL_UART2_RX
// Uncomment next #define for testing with ICCA board
// #define USE_ICCA_CU_PA_UART_SNOOPING
//Define the com port assignations
//----------------------------
#define DRIVE_UART_PORT UART_1
#ifdef USE_ICCA_CU_PA_UART_SNOOPING
// Note: With this configuration there is no CU command going to the PA
#define CU_UART_PORT UART_3
#define CONSOLE_UART_PORT UART_2
#else
// Normal setting using PA SPI for UART_3 (CONSOLE_UART_PORT)
#define CU_UART_PORT UART_2
#define CONSOLE_UART_PORT UART_3
#endif
#define ACTUATOR_WITTENSTEIN
//#define ACTUATOR_DS50
//
//----------------------------
//#define USE_BLOCKING_PRINTF
#define USE_PRINTF
#ifdef USE_PRINTF
#define PRINTF(n, a...) printf(n, ## a)
#else
#define PRINTF(n, a...)
#define NO_EXTERNAL_UART
#endif
/* ************************************************************************** */
/* Type definitions */
typedef int bool;
#endif
//EOF

View File

@ -0,0 +1,129 @@
/******************************************************************************/
/* Files to Include */
/******************************************************************************/
#include <plib.h> /* Include to use PIC32 peripheral libraries */
#include <stdint.h> /* For uint32_t definition */
#include <stdbool.h> /* For true/false definition */
/******************************************************************************/
/* Exception Macro Definitions */
/******************************************************************************/
/*When WRITE_EXCEPTION_CAUSE_TO_FLASH is defined the PIC32 executes a self
write routine to save the exception cause register.*/
/* #define WRITE_EXCEPTION_CAUSE_TO_FLASH */
#ifdef WRITE_EXCEPTION_CAUSE_TO_FLASH
/* Physical Addresses which are at the end of KSEG 0 program memory. */
/* User may want to adjust these values */
#define EXCEPTION_CAUSE 0x1D007FFC
#define EXCEPTION_ADDR 0x1D007FF8
#endif
/******************************************************************************/
/* Exception Variable Declaration */
/******************************************************************************/
/* static in case exception condition would stop auto variable being created */
static enum {
EXCEP_IRQ = 0, /* interrupt */
EXCEP_AdEL = 4, /* address error exception (load or ifetch) */
EXCEP_AdES, /* address error exception (store) */
EXCEP_IBE, /* bus error (ifetch) */
EXCEP_DBE, /* bus error (load/store) */
EXCEP_Sys, /* syscall */
EXCEP_Bp, /* breakpoint */
EXCEP_RI, /* reserved instruction */
EXCEP_CpU, /* coprocessor unusable */
EXCEP_Overflow, /* arithmetic overflow */
EXCEP_Trap, /* trap (possible divide by zero) */
EXCEP_IS1 = 16, /* implementation specfic 1 */
EXCEP_CEU, /* CorExtend Unuseable */
EXCEP_C2E /* coprocessor 2 */
} _excep_code;
/* static in case exception condition would stop auto variable being created */
static unsigned int _epc_code;
static unsigned int _excep_addr;
/******************************************************************************/
/* Exception Handling */
/******************************************************************************/
/* This function overrides the normal _weak_ _generic_exception_handler which
is defined in the C32 User's Guide. The _weak_ _generic_exception_handler
just does an infinite loop. */
void _general_exception_handler(void)
{
unsigned long t0 = _CP0_GET_COUNT(); /* Used for NVMOP 6 us Delay */
/* Mask off Mask of the ExcCode Field from the Cause Register
Refer to the MIPs M4K Software User's manual */
_excep_code=_CP0_GET_CAUSE() & 0x0000007C >> 2;
_excep_addr=_CP0_GET_EPC();
_CP0_SET_STATUS(_CP0_GET_STATUS()&0xFFFFFFE); /* Disable Interrupts */
#ifdef WRITE_EXCEPTION_CAUSE_TO_FLASH
/* Store the exception causes in program memory in case the part exhibited
the problem in release mode. Gives user a place to start debugging
the problem. */
NVMCON = 0x4001; /* set WREN and Word Programing mode */
NVMADDR = EXCEPTION_CAUSE; /* PM Address at which we'll store the */
/* cause register */
NVMDATA = _excep_code;
/* wait at least 6 us for LVD start-up
assume we're running at max frequency
(80 MHz) so we're always safe */
{
while (_CP0_GET_COUNT() - t0 < (80/2)*6);
}
NVMKEY = 0xAA996655;
NVMKEY = 0x556699AA; /* unlock sequence */
NVMCONSET = NVMCON_WR;
while(NVMCON & NVMCON_WR); /* wait on write to finish */
NVMCON = 0x4001; /* set WREN and Word Programing mode */
NVMADDR = EXCEPTION_ADDR; /* PM Address at which we'll store the */
/* exception address register */
NVMDATA = _excep_addr;
/* wait at least 6 us for LVD start-up
assume we're running at max frequency
(80 MHz) so we're always safe */
{
while (_CP0_GET_COUNT() - t0 < (80/2)*6);
}
NVMKEY = 0xAA996655;
NVMKEY = 0x556699AA; /* unlock sequence */
NVMCONSET = NVMCON_WR;
while(NVMCON & NVMCON_WR);
/* Write the exception cause and address to the part can be read and
the cause determined. */
NVMWriteWord((void*)EXCEPTION_CAUSE, _excep_code);
NVMWriteWord((void*)EXCEPTION_ADDR, _excep_addr);
#endif
while (1)
{
/* Examine _excep_code to identify the type of exception */
/* Examine _excep_addr to find the address that caused the exception */
Nop();
Nop();
Nop();
SoftReset();
Nop();
}
}

View File

@ -0,0 +1,649 @@
/**
* ---------------------------------------------------------------+
* @desc HD44780 LCD Driver
* ---------------------------------------------------------------+
* Copyright (C) 2020 Marian Hrinko.
* Written by Marian Hrinko (mato.hrinko@gmail.com)
*
* @author Marian Hrinko
* @datum 18.11.2020
* @file hd44780.c
* @tested AVR Atmega16a
*
* @depend hd44780.h
* ---------------------------------------------------------------+
* @usage default set 16x2 LCD
* 4-bit with 3 control wires (RW, RS, E)
*/
// include libraries
#include <stdio.h>
//#include <util/delay.h>
//#include <avr/io.h>
#include "hd44780.h"
#include "timer.h"
// +---------------------------+
// | Power on |
// | Wait for more than 15 ms | // 15 ms wait
// | after VCC rises to 4.5 V |
// +---------------------------+
// |
// +---------------------------+
// | RS R/W DB7 DB6 DB5 DB4 |
// | 0 0 0 0 1 1 | // Initial sequence 0x30
// | Wait for more than 4.1 ms | // 4.1 ms us writing DATA into DDRAM or CGRAM
// +---------------------------+
// |
// +---------------------------+
// | RS R/W DB7 DB6 DB5 DB4 |
// | 0 0 0 0 1 1 | // Initial sequence 0x30
// | Wait for more than 0.1 ms | // 100 us writing DATA into DDRAM or CGRAM
// +---------------------------+
// |
// +---------------------------+
// | RS R/W DB7 DB6 DB5 DB4 | // Initial sequence 0x30
// | 0 0 0 0 1 1 | // 37 us writing DATA into DDRAM or CGRAM 4 us tadd - time after busy flag disapeared
// | Wait for more than 45 us | // 37 us + 4 us = 41 us * (270/250) = 45us
// +---------------------------+
// |
// +---------------------------+ // 4bit mode 0x20 !!! MUST BE SET TIME, BF CHECK DOESN'T WORK CORRECTLY !!!
// | RS R/W DB7 DB6 DB5 DB4 | //
// | 0 0 0 0 1 0 | // 37 us writing DATA into DDRAM or CGRAM 4 us tadd - time after busy flag disapeared
// | Wait for more than 45 us | // !!! MUST BE SET DELAY TIME, BUSY FLAG CHECK DOESN'T WORK CORRECTLY !!!
// +---------------------------+
// |
// +---------------------------+
// | RS R/W DB7 DB6 DB5 DB4 | // Display off 0x08
// | 0 0 0 0 1 0 | //
// | 0 0 1 0 0 0 | //
// | Wait for BF Cleared | // Wait for BF Cleared
// +---------------------------+
// |
// +---------------------------+
// | RS R/W DB7 DB6 DB5 DB4 | // Display clear 0x01
// | 0 0 0 0 0 0 | //
// | 0 0 0 0 0 1 | //
// | Wait for BF Cleared | // Wait for BF Cleared
// +---------------------------+
// |
// +---------------------------+
// | RS R/W DB7 DB6 DB5 DB4 | // Entry mode set 0x06
// | 0 0 0 0 0 0 | //
// | 0 0 0 1 1 0 | // shift cursor to the left, without text shifting
// | Wait for BF Cleared | // Wait for BF Cleared
// +---------------------------+
/**
* @desc LCD display clear
*
* @param void
*
* @return void
*/
void HD44780_DisplayClear (void)
{
// Diplay clear
HD44780_SendInstruction(HD44780_DISP_CLEAR);
}
/**
* @desc LCD display on
*
* @param void
*
* @return void
*/
void HD44780_DisplayOn (void)
{
// send instruction - display on
HD44780_SendInstruction(HD44780_DISP_ON);
}
/**
* @desc LCD cursor on, display on
*
* @param void
*
* @return void
*/
void HD44780_CursorOn (void)
{
// send instruction - cursor on
HD44780_SendInstruction(HD44780_CURSOR_ON);
}
/**
* @desc LCD cursor off
*
* @param void
*
* @return void
*/
void HD44780_CursorOff (void)
{
// send instruction - cursor on
HD44780_SendInstruction(HD44780_CURSOR_OFF);
}
/**
* @desc LCD cursor blink, cursor on, display on
*
* @param void
*
* @return void
*/
void HD44780_CursorBlink (void)
{
// send instruction - Cursor blink
HD44780_SendInstruction(HD44780_CURSOR_BLINK);
}
/**
* @desc LCD draw char
*
* @param char
*
* @return void
*/
void HD44780_DrawChar (char character)
{
// Diplay clear
HD44780_SendData(character);
}
/**
* @desc LCD draw string
*
* @param char *
*
* @return void
*/
void HD44780_DrawString (char *str)
{
unsigned char i = 0;
// loop through 5 bytes
while (str[i] != '\0') {
//read characters and increment index
HD44780_SendData(str[i++]);
}
}
/**
* @desc Got to position x,y
*
* @param char
* @param char
*
* @return char
*/
char HD44780_PositionXY (char x, char y)
{
if (x > HD44780_COLS || y > HD44780_ROWS) {
// error
return ERROR;
}
// check which row
if (y == 0) {
// send instruction 1st row
HD44780_SendInstruction(HD44780_POSITION | (HD44780_ROW1_START + x));
} else if (y == 1) {
// send instruction 2nd row
HD44780_SendInstruction(HD44780_POSITION | (HD44780_ROW2_START + x));
}
// success
return 0;
}
/**
* @desc Shift cursor / display to left / right
*
* @param char item {HD44780_CURSOR; HD44780_DISPLAY}
* @param char direction {HD44780_RIGHT; HD44780_LEFT}
*
* @return char
*/
char HD44780_Shift (char item, char direction)
{
// check if item is cursor or display or direction is left or right
if ((item != HD44780_DISPLAY) && (item != HD44780_CURSOR)) {
// error
return ERROR;
}
// check if direction is left or right
if ((direction != HD44780_RIGHT) && (direction != HD44780_LEFT)) {
// error
return ERROR;
}
// cursor shift
if (item == HD44780_CURSOR) {
// right shift
if (direction == HD44780_RIGHT) {
// shit cursor / display to right / left
HD44780_SendInstruction(HD44780_SHIFT | HD44780_CURSOR | HD44780_RIGHT);
} else {
// shit cursor / display to right / left
HD44780_SendInstruction(HD44780_SHIFT | HD44780_CURSOR | HD44780_LEFT);
}
// display shift
} else {
// right shift
if (direction == HD44780_RIGHT) {
// shit cursor / display to right / left
HD44780_SendInstruction(HD44780_SHIFT | HD44780_DISPLAY | HD44780_RIGHT);
} else {
// shit cursor / display to right / left
HD44780_SendInstruction(HD44780_SHIFT | HD44780_DISPLAY | HD44780_LEFT);
}
}
// success
return 0;
}
/**
* @desc LCD init - initialisation routine
*
* @param void
*
* @return void
*/
void HD44780_Init (void)
{
// set E as output
SETBIT(HD44780_DDR_E, HD44780_E);
// set RS as output
SETBIT(HD44780_DDR_RS, HD44780_RS);
// set RW as output
SETBIT(HD44780_DDR_RW, HD44780_RW);
// set DB7-DB4 as output
HD44780_SetDDR_DATA4to7();
// clear RS
CLRBIT(HD44780_PORT_RS, HD44780_RS);
// clear RW
CLRBIT(HD44780_PORT_RW, HD44780_RW);
// clear E
CLRBIT(HD44780_PORT_E, HD44780_E);
// delay > 15ms
_delay_ms(16);
// Busy Flag (BF) cannot be checked in these instructions
// ---------------------------------------------------------------------
// Initial sequence 0x30 - send 4 bits in 4 bit mode
HD44780_SendInstruction(HD44780_INIT_SEQ);
// delay > 4.1ms
_delay_ms(5);
// pulse E
HD44780_PulseE();
// delay > 100us
_delay_us(110);
// pulse E
HD44780_PulseE();
// delay > 45us (=37+4 * 270/250)
_delay_us(50);
// 4 bit mode 0x20 - send 4 bits in 4 bit mode
HD44780_Send4bitsIn4bitMode(HD44780_4BIT_MODE);
// pulse E
HD44780_PulseE();
// delay > 45us (=37+4 * 270/250)
_delay_us(50);
// ----------------------------------------------------------------------
// 4-bit & 2-lines & 5x8-dots 0x28 - send 8 bits in 4 bit mode
HD44780_SendInstruction(HD44780_4BIT_MODE | HD44780_2_ROWS | HD44780_FONT_5x8);
// display off 0x08 - send 8 bits in 4 bit mode
HD44780_SendInstruction(HD44780_DISP_OFF);
// display clear 0x01 - send 8 bits in 4 bit mode
HD44780_SendInstruction(HD44780_DISP_CLEAR);
// entry mode set 0x06 - send 8 bits in 4 bit mode
HD44780_SendInstruction(HD44780_ENTRY_MODE);
}
/**
* @desc Check Busy Flag (BF) in 4 bit mode
*
* @param void
*
* @return void
*/
void HD44780_CheckBFin4bitMode (void)
{
unsigned char input = 0;
// clear DB7-DB4 as input
HD44780_ClearDDR_DATA4to7();
// set pull-up resistors for DB7-DB4
HD44780_SetPORT_DATA4to7();
// clear RS
CLRBIT(HD44780_PORT_RS, HD44780_RS);
// set RW - read instruction
SETBIT(HD44780_PORT_RW, HD44780_RW);
// test HIGH level on PIN DB7
// after clear PIN DB7 should continue
// -------------------------------------
// us: 0.5|0.5|0.5
// ___ ___
// E: ___/ \___/ \__
// ___ ___
// DB7: \___/ \___/ \__
//
while (1) {
// Read upper nibble
// --------------------------------
// Set E
SETBIT(HD44780_PORT_E, HD44780_E);
// PWeh > 0.5us
_delay_us(0.5);
// read upper nibble (tDDR > 360ns)
input = HD44780_PIN_DATA;
// Clear E
CLRBIT(HD44780_PORT_E, HD44780_E);
// TcycE > 1000ns -> delay depends on PWeh delay time
// delay = TcycE - PWeh = 1000 - 500 = 500ns
_delay_us(0.5);
// Read lower nibble
// --------------------------------
// Set E
SETBIT(HD44780_PORT_E, HD44780_E);
// PWeh > 0.5us
_delay_us(0.5);
// read lower nibble (tDDR > 360ns)
input |= HD44780_PIN_DATA >> 4;
// Clear E
CLRBIT(HD44780_PORT_E, HD44780_E);
// TcycE > 1000ns -> delay depends on PWeh delay time
// delay = TcycE - PWeh = 1000 - 500 = 500ns
_delay_us(0.5);
// check if DB7 is cleared
if (!(input & (1 << HD44780_DATA7))) {
// if BF cleared -> end loop
break;
}
}
// clear RW
CLRBIT(HD44780_PORT_RW, HD44780_RW);
// set DB7-DB4 as output
HD44780_SetDDR_DATA4to7();
}
/**
* @desc Check Busy Flag (BF) in 8 bit mode
*
* @param void
* @return void
*/
void HD44780_CheckBFin8bitMode (void)
{
}
/**
* @desc LCD send instruction
*
* @param unsigned short int
*
* @return void
*/
void HD44780_SendInstruction (unsigned short int data)
{
// Clear RS
HD44780_PORT_RS &= ~(1 << HD44780_RS);
// 4bit mode
// ------------------------------------------
if (HD44780_MODE == HD44780_4BIT_MODE) {
// send required data in required mode
HD44780_Send8bitsIn4bitMode(data);
// check busy flag
HD44780_CheckBFin4bitMode();
// 8 bit mode
// ------------------------------------------
} else if (HD44780_MODE == HD44780_8BIT_MODE) {
// send required data in required mode
HD44780_Send8bitsIn8bitMode(data);
// check busy flag
HD44780_CheckBFin8bitMode();
}
}
/**
* @desc LCD send data
*
* @param unsigned short int
*
* @return void
*/
void HD44780_SendData (unsigned short int data)
{
// Set RS
SETBIT(HD44780_PORT_RS, HD44780_RS);
// 4bit mode
// ------------------------------------------
if (HD44780_MODE == HD44780_4BIT_MODE) {
// send required data in required mode
HD44780_Send8bitsIn4bitMode(data);
// check busy flag
HD44780_CheckBFin4bitMode();
// 8 bit mode
// ------------------------------------------
} else if (HD44780_MODE == HD44780_8BIT_MODE) {
// send required data in required mode
HD44780_Send8bitsIn8bitMode(data);
// check busy flag
HD44780_CheckBFin8bitMode();
}
// Clear RS
CLRBIT(HD44780_PORT_RS, HD44780_RS);
}
/**
* @desc LCD send 4bits instruction in 4 bit mode
*
* @param unsigned short int
*
* @return void
*/
void HD44780_Send4bitsIn4bitMode (unsigned short int data)
{
// Set E
SETBIT(HD44780_PORT_E, HD44780_E);
// send data to LCD
HD44780_SetUppNibble(data);
// PWeh delay time > 450ns
_delay_us(0.5);
// Clear E
CLRBIT(HD44780_PORT_E, HD44780_E);
// TcycE > 1000ns -> delay depends on PWeh delay time
// delay = TcycE - PWeh = 1000 - 500 = 500ns
_delay_us(0.5);
}
/**
* @desc LCD send 8bits instruction in 4 bit mode
*
* @param unsigned short int
*
* @return void
*/
void HD44780_Send8bitsIn4bitMode (unsigned short int data)
{
// Send upper nibble
// ----------------------------------
// Set E
SETBIT(HD44780_PORT_E, HD44780_E);
// send data to LCD
HD44780_SetUppNibble(data);
// PWeh delay time > 450ns
_delay_us(0.5);
// Clear E
CLRBIT(HD44780_PORT_E, HD44780_E);
// TcycE > 1000ns -> delay depends on PWeh delay time
// delay = TcycE - PWeh = 1000 - 500 = 500ns
_delay_us(0.5);
// Send lower nibble
// ----------------------------------
// Set E
SETBIT(HD44780_PORT_E, HD44780_E);
// send data to LCD
HD44780_SetUppNibble(data << 4);
// PWeh delay time > 450ns
_delay_us(0.5);
// Clear E
CLRBIT(HD44780_PORT_E, HD44780_E);
// TcycE > 1000ns -> delay depends on PWeh delay time
// delay = TcycE - PWeh = 1000 - 500 = 500ns
_delay_us(0.5);
}
/**
* @desc LCD send 8bits instruction in 8 bit mode
*
* @param unsigned short int
*
* @return void
*/
void HD44780_Send8bitsIn8bitMode (unsigned short int data)
{
// Set E
SETBIT(HD44780_PORT_E, HD44780_E);
// send data to LCD
HD44780_SetUppNibble(data);
// send data to LCD
HD44780_SetLowNibble(data);
// PWeh delay time > 450ns
_delay_us(0.5);
// Clear E
CLRBIT(HD44780_PORT_E, HD44780_E);
// TcycE > 1000ns -> delay depends on PWeh delay time
// delay = TcycE - PWeh = 1000 - 500 = 500ns
_delay_us(0.5);
}
/**
* @desc LCD send upper nibble
*
* @param unsigned short int
*
* @return void
*/
void HD44780_SetUppNibble (unsigned short int data)
{
// clear bits DB7-DB4
CLRBIT(HD44780_PORT_DATA, HD44780_DATA7);
CLRBIT(HD44780_PORT_DATA, HD44780_DATA6);
CLRBIT(HD44780_PORT_DATA, HD44780_DATA5);
CLRBIT(HD44780_PORT_DATA, HD44780_DATA4);
// set DB7-DB4 if corresponding bit is set
if (data & 0x80) { SETBIT(HD44780_PORT_DATA, HD44780_DATA7); }
if (data & 0x40) { SETBIT(HD44780_PORT_DATA, HD44780_DATA6); }
if (data & 0x20) { SETBIT(HD44780_PORT_DATA, HD44780_DATA5); }
if (data & 0x10) { SETBIT(HD44780_PORT_DATA, HD44780_DATA4); }
}
/**
* @desc LCD send lower nibble
*
* @param unsigned short int
*
* @return void
*/
void HD44780_SetLowNibble (unsigned short int data)
{
// clear bits DB7-DB4
CLRBIT(HD44780_PORT_DATA, HD44780_DATA3);
CLRBIT(HD44780_PORT_DATA, HD44780_DATA2);
CLRBIT(HD44780_PORT_DATA, HD44780_DATA1);
CLRBIT(HD44780_PORT_DATA, HD44780_DATA0);
// set DB7-DB4 if corresponding bit is set
if (data & 0x08) { SETBIT(HD44780_PORT_DATA, HD44780_DATA3); }
if (data & 0x04) { SETBIT(HD44780_PORT_DATA, HD44780_DATA2); }
if (data & 0x02) { SETBIT(HD44780_PORT_DATA, HD44780_DATA1); }
if (data & 0x01) { SETBIT(HD44780_PORT_DATA, HD44780_DATA0); }
}
/**
* @desc LCD pulse E
*
* @param void
*
* @return void
*/
void HD44780_PulseE (void)
{
// Set E
SETBIT(HD44780_PORT_E, HD44780_E);
// PWeh delay time > 450ns
_delay_us(0.5);
// Clear E
CLRBIT(HD44780_PORT_E, HD44780_E);
// TcycE > 1000ns -> delay depends on PWeh delay time
// delay = TcycE - PWeh = 1000 - 500 = 500ns
_delay_us(0.5);
}
/**
* @desc Set PORT DB4 to DB7
*
* @param void
*
* @return void
*/
void HD44780_SetPORT_DATA4to7 (void)
{
// set DB4-DB7
SETBIT(HD44780_PORT_DATA, HD44780_DATA4);
SETBIT(HD44780_PORT_DATA, HD44780_DATA5);
SETBIT(HD44780_PORT_DATA, HD44780_DATA6);
SETBIT(HD44780_PORT_DATA, HD44780_DATA7);
}
/**
* @desc Clear DDR DB4 to DB7
*
* @param void
*
* @return void
*/
void HD44780_ClearDDR_DATA4to7 (void)
{
// set DB4-DB7
CLRBIT(HD44780_DDR_DATA, HD44780_DATA4);
CLRBIT(HD44780_DDR_DATA, HD44780_DATA5);
CLRBIT(HD44780_DDR_DATA, HD44780_DATA6);
CLRBIT(HD44780_DDR_DATA, HD44780_DATA7);
}
/**
* @desc Set DDR DB4 to DB7
*
* @param void
*
* @return void
*/
void HD44780_SetDDR_DATA4to7 (void)
{
// set DB7-DB4 as output
SETBIT(HD44780_DDR_DATA, HD44780_DATA4);
SETBIT(HD44780_DDR_DATA, HD44780_DATA5);
SETBIT(HD44780_DDR_DATA, HD44780_DATA6);
SETBIT(HD44780_DDR_DATA, HD44780_DATA7);
}

View File

@ -0,0 +1,386 @@
/**
* ---------------------------------------------------------------+
* @desc HD44780 LCD Driver
* ---------------------------------------------------------------+
* Copyright (C) 2020 Marian Hrinko.
* Written by Marian Hrinko (mato.hrinko@gmail.com)
*
* @author Marian Hrinko
* @datum 18.11.2020
* @file hd44780.c
* @tested AVR Atmega16a
*
* @depend
* ---------------------------------------------------------------+
* @usage default set 16x2 LCD
* 4-bit with 3 control wires (RW, RS, E)
*
*/
#ifndef __HD44780_H__
#define __HD44780_H__
// Success
#ifndef SUCCESS
#define SUCCESS 0
#endif
// Error
#ifndef ERROR
#define ERROR 1
#endif
// define clock
#if defined(__AVR_ATmega8__)
#define _FCPU 8000000
#elif defined(__AVR_ATmega16__)
#define _FCPU 16000000
#endif
//#if defined(__AVR_ATmega16__)
// E port
// --------------------------------------
#ifndef HD44780_DDR_E
#define HD44780_DDR_E TRISB
#endif
#ifndef HD44780_PORT_E
#define HD44780_PORT_E PORTB
#endif
#ifndef HD44780_E
#define HD44780_E 12
#endif
// RW port
// --------------------------------------
#ifndef HD44780_DDR_RW
#define HD44780_DDR_RW TRISB
#endif
#ifndef HD44780_PORT_RW
#define HD44780_PORT_RW PORTB
#endif
#ifndef HD44780_RW
#define HD44780_RW 13
#endif
// RS port
// --------------------------------------
#ifndef HD44780_DDR_RS
#define HD44780_DDR_RS TRISD
#endif
#ifndef HD44780_PORT_RS
#define HD44780_PORT_RS PORTD
#endif
#ifndef HD44780_RS
#define HD44780_RS 5
#endif
// DATA port / pin
// --------------------------------------
#ifndef HD44780_DDR_DATA
#define HD44780_DDR_DATA TRISB
#endif
#ifndef HD44780_PORT_DATA
#define HD44780_PORT_DATA PORTB
#endif
#ifndef HD44780_PIN_DATA
#define HD44780_PIN_DATA PORTB
#endif
// pins
#ifndef HD44780_DATA7
#define HD44780_DATA7 11 // LCD PORT DB7
#endif
#ifndef HD44780_DATA6
#define HD44780_DATA6 10 // LCD PORT DB6
#endif
#ifndef HD44780_DATA5
#define HD44780_DATA5 9 // LCD PORT DB5
#endif
#ifndef HD44780_DATA4
#define HD44780_DATA4 3 // LCD PORT DB4
#endif
#ifndef HD44780_DATA3
#define HD44780_DATA3 0 // LCD PORT DB3
#endif
#ifndef HD44780_DATA2
#define HD44780_DATA2 0 // LCD PORT DB2
#endif
#ifndef HD44780_DATA1
#define HD44780_DATA1 0 // LCD PORT DB1
#endif
#ifndef HD44780_DATA0
#define HD44780_DATA0 0 // LCD PORT DB0
#endif
// #endif
#define _delay_ms(x) Sleep(x)
#define _delay_us(x) Sleep(1)
#define BIT7 0x80
#define BIT6 0x40
#define BIT5 0x20
#define BIT4 0x10
#define BIT3 0x08
#define BIT2 0x04
#define BIT1 0x02
#define BIT0 0x01
#define HD44780_BUSY_FLAG HD44780_DATA7
#define HD44780_INIT_SEQ 0x30
#define HD44780_DISP_CLEAR 0x01
#define HD44780_DISP_OFF 0x08
#define HD44780_DISP_ON 0x0C
#define HD44780_CURSOR_ON 0x0E
#define HD44780_CURSOR_OFF 0x0C
#define HD44780_CURSOR_BLINK 0x0F
#define HD44780_RETURN_HOME 0x02
#define HD44780_ENTRY_MODE 0x06
#define HD44780_4BIT_MODE 0x20
#define HD44780_8BIT_MODE 0x30
#define HD44780_2_ROWS 0x08
#define HD44780_FONT_5x8 0x00
#define HD44780_FONT_5x10 0x04
#define HD44780_POSITION 0x80
#define HD44780_SHIFT 0x10
#define HD44780_CURSOR 0x00
#define HD44780_DISPLAY 0x08
#define HD44780_LEFT 0x00
#define HD44780_RIGHT 0x04
#define HD44780_ROWS 2
#define HD44780_COLS 16
#define HD44780_ROW1_START 0x00
#define HD44780_ROW1_END HD44780_COLS
#define HD44780_ROW2_START 0x40
#define HD44780_ROW2_END HD44780_COLS
// **********************************************
// !!!
// MODE DEFINITION - CORRECTLY DEFINED
//
// ----------------------------------------------
//
// HD44780_4BIT_MODE - 4 bit mode / 4 data wires
// HD44780_8BIT_MODE - 8 bit mode / 8 data wires
//
// **********************************************
#define HD44780_MODE HD44780_4BIT_MODE
// set bit
#define SETBIT(REG, BIT) { REG |= (1 << BIT); }
// clear bit
#define CLRBIT(REG, BIT) { REG &= ~(1 << BIT); }
// set port / pin if bit is set
#define SET_IF_BIT_IS_SET(REG, PORT, DATA, BIT) { if((DATA & BIT) > 0) { SETBIT(REG, PORT); } }
/**
* @desc LCD init - initialisation routine
*
* @param void
*
* @return void
*/
void HD44780_Init (void);
/**
* @desc LCD display clear
*
* @param void
*
* @return void
*/
void HD44780_DisplayClear (void);
/**
* @desc LCD display on
*
* @param void
*
* @return void
*/
void HD44780_DisplayOn (void);
/**
* @desc LCD cursor on, display on
*
* @param void
*
* @return void
*/
void HD44780_CursorOn (void);
/**
* @desc LCD cursor off
*
* @param void
*
* @return void
*/
void HD44780_CursorOff (void);
/**
* @desc LCD cursor blink, cursor on, display on
*
* @param void
*
* @return void
*/
void HD44780_CursorBlink (void);
/**
* @desc LCD draw char
*
* @param char
* @return void
*/
void HD44780_DrawChar (char character);
/**
* @desc LCD draw string
*
* @param char *
*
* @return void
*/
void HD44780_DrawString (char *str);
/**
* @desc Got to position x,y
*
* @param char
* @param char
*
* @return char
*/
char HD44780_PositionXY (char x, char y);
/**
* @desc Shift cursor / display to left / right
*
* @param char item {HD44780_CURSOR; HD44780_DISPLAY}
* @param char direction {HD44780_RIGHT; HD44780_LEFT}
*
* @return char
*/
char HD44780_Shift (char item, char direction);
/**
* @desc Check Busy Flag (BF) in 8 bit mode
*
* @param void
*
* @return void
*/
void HD44780_CheckBFin8bitMode (void);
/**
* @desc Check Busy Flag (BF) in 4 bit mode
*
* @param void
*
* @return void
*/
void HD44780_CheckBFin4bitMode (void);
/**
* @desc LCD send instruction
*
* @param unsigned short int
*
* @return void
*/
void HD44780_SendInstruction (unsigned short int);
/**
* @desc LCD send data
*
* @param unsigned short int
*
* @return void
*/
void HD44780_SendData (unsigned short int);
/**
* @desc LCD send 4bits instruction in 4 bit mode
*
* @param unsigned short int
*
* @return void
*/
void HD44780_Send4bitsIn4bitMode (unsigned short int);
/**
* @desc LCD send 8bits instruction in 4 bit mode
*
* @param unsigned short int
*
* @return void
*/
void HD44780_Send8bitsIn4bitMode (unsigned short int);
/**
* @desc LCD send 8bits instruction in 8 bit mode
*
* @param unsigned short int
*
* @return void
*/
void HD44780_Send8bitsIn8bitMode (unsigned short int);
/**
* @desc LCD send upper nibble
*
* @param unsigned short int
*
* @return void
*/
void HD44780_SetUppNibble (unsigned short int);
/**
* @desc LCD send lower nibble
*
* @param unsigned short int
*
* @return void
*/
void HD44780_SetLowNibble (unsigned short int);
/**
* @desc LCD pulse E
*
* @param void
*
* @return void
*/
void HD44780_PulseE (void);
/**
* @desc Set PORT DB4 to DB7
*
* @param void
*
* @return void
*/
void HD44780_SetPORT_DATA4to7 (void);
/**
* @desc Set DDR DB4 to DB7
*
* @param void
*
* @return void
*/
void HD44780_SetDDR_DATA4to7 (void);
/**
* @desc Clear DDR DB4 to DB7
*
* @param void
*
* @return void
*/
void HD44780_ClearDDR_DATA4to7 (void);
#endif

View File

@ -0,0 +1,678 @@
/**************************************************************************/
/*!
@file ina219.c
@author K. Townsend (microBuilder.eu)
@brief Driver for the TI INA219 current/power monitor
@section DESCRIPTION
The INA219 is an I2C-based current/power monitor that monitors the
voltage drop across a shunt resistor, as well as the supply voltage.
@section EXAMPLE
@code
ina219Init();
int16_t current = 0;
int16_t power = 0;
int16_t current_mA = 0;
int16_t power_mW = 0;
int16_t busvoltage = 0;
int16_t shuntvoltage = 0;
int16_t loadVoltage = 0;
while(1)
{
shuntvoltage = ina219GetShuntVoltage();
busvoltage = ina219GetBusVoltage();
power = ina219GetPower();
current = ina219GetCurrent();
power_mW = ina219GetPower_mW();
current_mA = ina219GetCurrent_mA();
loadVoltage = busvoltage + (shuntvoltage / 100);
printf("%-15s %6d = %d.%dmV (%duV) \r\n", "Shunt Voltage:", shuntvoltage, shuntvoltage / 100, shuntvoltage % 100, shuntvoltage * 10);
printf("%-15s %6d = %d.%dV \r\n", "Bus Voltage:", busvoltage, busvoltage / 1000, busvoltage % 1000);
printf("%-15s %6d = %d.%dV \r\n", "Load Voltage:", loadVoltage, loadVoltage / 1000, loadVoltage % 1000);
printf("%-15s %6d = %dmW \r\n", "Power:", power, power_mW);
printf("%-15s %6d = %dmA \r\n", "Current:", current, current_mA);
printf("\r\n");
systickDelay(5000);
}
@endcode
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2012 Kevin Townsend
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
#include "ina219.h"
#include "I2C.h"
#include <stdint.h>
unsigned char I2CMasterBuffer[I2C_BUFSIZE];
unsigned char I2CSlaveBuffer[I2C_BUFSIZE];
// The following multipliers are used to convert raw current and power
// values to mA and mW, taking into account the current config settings
uint32_t ina219_currentDivider_mA = 0;
uint32_t ina219_powerDivider_mW = 0;
/**************************************************************************/
/*!
@brief Sends a single command byte over I2C
*/
/**************************************************************************/
static int ina219WriteRegister (uint8_t reg, uint16_t value)
{
// Clear write buffers
uint32_t i;
for ( i = 0; i < I2C_BUFSIZE; i++ )
{
I2CMasterBuffer[i] = 0x00;
}
//I2CWriteLength = 4;
// I2CReadLength = 0;
I2CMasterBuffer[0] = INA219_ADDRESS; // I2C device address
I2CMasterBuffer[1] = reg; // Register
I2CMasterBuffer[2] = value >> 8; // Upper 8-bits
I2CMasterBuffer[3] = value & 0xFF; // Lower 8-bits
return I2CWrite(I2CMasterBuffer,4);
//i2cEngine();
}
/**************************************************************************/
/*!
@brief Reads a 16 bit values over I2C
*/
/**************************************************************************/
static void ina219Read16(uint8_t reg, uint16_t *value)
{
// Clear write buffers
int RET = RET_OK;
uint32_t i;
for ( i = 0; i < I2C_BUFSIZE; i++ )
{
I2CMasterBuffer[i] = 0x00;
}
// I2CWriteLength = 2;
//I2CReadLength = 2;
I2CMasterBuffer[0] = INA219_ADDRESS; // I2C device address
I2CMasterBuffer[1] = reg; // Command register
// Append address w/read bit
I2CMasterBuffer[2] = INA219_ADDRESS | INA219_READ;
// i2cEngine();
I2CWrite(I2CMasterBuffer,2); //write pointer to the good register
RET = I2CRead(I2CMasterBuffer[2],&I2CSlaveBuffer[0],2); //read the data
if(RET != RET_OK)
{
* value = 0;
return;
}
// Shift values to create properly formed integer
*value = ((I2CSlaveBuffer[0] << 8) | I2CSlaveBuffer[1]);
}
void ina219SetCalibration_13V_10A(void)
{
// By default we use a pretty huge range for the input voltage,
// which probably isn't the most appropriate choice for system
// that don't use a lot of power. But all of the calculations
// are shown below if you want to change the settings. You will
// also need to change any relevant register settings, such as
// setting the VBUS_MAX to 16V instead of 32V, etc.
// VBUS_MAX = 13V (Assumes 32V, can also be set to 16V)
// VSHUNT_MAX = 0.32 (Assumes Gain 8, 320mV, can also be 0.16, 0.08, 0.04)
// RSHUNT = 0.1 (Resistor value in ohms)
// 1. Determine max possible current
// MaxPossible_I = VSHUNT_MAX / RSHUNT
// MaxPossible_I = 3.2A
// 2. Determine max expected current
// MaxExpected_I = 3.2A
// 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
// MinimumLSB = MaxExpected_I/32767
// MinimumLSB = 0.00009765 (98µA per bit)
// MaximumLSB = MaxExpected_I/4096
// MaximumLSB = 0,000488 (488µA per bit)
// 4. Choose an LSB between the min and max values
// (Preferrably a roundish number close to MinLSB)
// CurrentLSB = 0.0001 (100µA per bit)
// 5. Compute the calibration register
// Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
// Cal = 4096 (0x1000)
// 6. Calculate the power LSB
// PowerLSB = 20 * CurrentLSB
// PowerLSB = 0.002 (2mW per bit)
// 7. Compute the maximum current and shunt voltage values before overflow
//
// Max_Current = Current_LSB * 32767
// Max_Current = 3.2767A before overflow
//
// If Max_Current > Max_Possible_I then
// Max_Current_Before_Overflow = MaxPossible_I
// Else
// Max_Current_Before_Overflow = Max_Current
// End If
//
// Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
// Max_ShuntVoltage = 0.32V
//
// If Max_ShuntVoltage >= VSHUNT_MAX
// Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX
// Else
// Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage
// End If
// 8. Computer the Maximum Power
// MaximumPower = Max_Current_Before_Overflow * VBUS_MAX
// MaximumPower = 3.2 * 32V
// MaximumPower = 102.4W
// Set multipliers to convert raw current/power values
ina219_currentDivider_mA = 10; // Current LSB = 100uA per bit (1000/100 = 10)
ina219_powerDivider_mW = 2; // Power LSB = 1mW per bit (2/1)
// Set Calibration register to 'Cal' calculated above
ina219WriteRegister(INA219_REG_CALIBRATION, 0x1000);
// Set Config register to take into account the settings above
uint16_t config = INA219_CONFIG_BVOLTAGERANGE_32V |
INA219_CONFIG_GAIN_8_320MV |
INA219_CONFIG_BADCRES_12BIT |
INA219_CONFIG_SADCRES_12BIT_1S_532US |
// INA219_CONFIG_MODE_SVOLT_CONTINUOUS;
INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS;
ina219WriteRegister(INA219_REG_CONFIG, config);
}
/**************************************************************************/
/*!
@brief Configures to INA219 to be able to measure up to 32V and 2A
of current. Each unit of current corresponds to 100uA, and
each unit of power corresponds to 2mW. Counter overflow
occurs at 3.2A.
@note These calculations assume a 0.1 ohm resistor is present
*/
/**************************************************************************/
void ina219SetCalibration_32V_2A(void)
{
// By default we use a pretty huge range for the input voltage,
// which probably isn't the most appropriate choice for system
// that don't use a lot of power. But all of the calculations
// are shown below if you want to change the settings. You will
// also need to change any relevant register settings, such as
// setting the VBUS_MAX to 16V instead of 32V, etc.
// VBUS_MAX = 32V (Assumes 32V, can also be set to 16V)
// VSHUNT_MAX = 0.32 (Assumes Gain 8, 320mV, can also be 0.16, 0.08, 0.04)
// RSHUNT = 0.1 (Resistor value in ohms)
// 1. Determine max possible current
// MaxPossible_I = VSHUNT_MAX / RSHUNT
// MaxPossible_I = 3.2A
// 2. Determine max expected current
// MaxExpected_I = 2.0A
// 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
// MinimumLSB = MaxExpected_I/32767
// MinimumLSB = 0.000061 (61µA per bit)
// MaximumLSB = MaxExpected_I/4096
// MaximumLSB = 0,000488 (488µA per bit)
// 4. Choose an LSB between the min and max values
// (Preferrably a roundish number close to MinLSB)
// CurrentLSB = 0.0001 (100µA per bit)
// 5. Compute the calibration register
// Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
// Cal = 4096 (0x1000)
// 6. Calculate the power LSB
// PowerLSB = 20 * CurrentLSB
// PowerLSB = 0.002 (2mW per bit)
// 7. Compute the maximum current and shunt voltage values before overflow
//
// Max_Current = Current_LSB * 32767
// Max_Current = 3.2767A before overflow
//
// If Max_Current > Max_Possible_I then
// Max_Current_Before_Overflow = MaxPossible_I
// Else
// Max_Current_Before_Overflow = Max_Current
// End If
//
// Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
// Max_ShuntVoltage = 0.32V
//
// If Max_ShuntVoltage >= VSHUNT_MAX
// Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX
// Else
// Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage
// End If
// 8. Computer the Maximum Power
// MaximumPower = Max_Current_Before_Overflow * VBUS_MAX
// MaximumPower = 3.2 * 32V
// MaximumPower = 102.4W
// Set multipliers to convert raw current/power values
ina219_currentDivider_mA = 10; // Current LSB = 100uA per bit (1000/100 = 10)
ina219_powerDivider_mW = 2; // Power LSB = 1mW per bit (2/1)
// Set Calibration register to 'Cal' calculated above
ina219WriteRegister(INA219_REG_CALIBRATION, 0x1000);
// Set Config register to take into account the settings above
uint16_t config = INA219_CONFIG_BVOLTAGERANGE_32V |
INA219_CONFIG_GAIN_8_320MV |
INA219_CONFIG_BADCRES_12BIT |
INA219_CONFIG_SADCRES_12BIT_1S_532US |
INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS;
ina219WriteRegister(INA219_REG_CONFIG, config);
}
/**************************************************************************/
/*!
@brief Configures to INA219 to be able to measure up to 32V and 1A
of current. Each unit of current corresponds to 40uA, and each
unit of power corresponds to 800µW. Counter overflow occurs at
1.3A.
@note These calculations assume a 0.1 ohm resistor is present
*/
/**************************************************************************/
void ina219SetCalibration_32V_1A(void)
{
// By default we use a pretty huge range for the input voltage,
// which probably isn't the most appropriate choice for system
// that don't use a lot of power. But all of the calculations
// are shown below if you want to change the settings. You will
// also need to change any relevant register settings, such as
// setting the VBUS_MAX to 16V instead of 32V, etc.
// VBUS_MAX = 32V (Assumes 32V, can also be set to 16V)
// VSHUNT_MAX = 0.32 (Assumes Gain 8, 320mV, can also be 0.16, 0.08, 0.04)
// RSHUNT = 0.1 (Resistor value in ohms)
// 1. Determine max possible current
// MaxPossible_I = VSHUNT_MAX / RSHUNT
// MaxPossible_I = 3.2A
// 2. Determine max expected current
// MaxExpected_I = 1.0A
// 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
// MinimumLSB = MaxExpected_I/32767
// MinimumLSB = 0.0000305 (30.5µA per bit)
// MaximumLSB = MaxExpected_I/4096
// MaximumLSB = 0.000244 (244µA per bit)
// 4. Choose an LSB between the min and max values
// (Preferrably a roundish number close to MinLSB)
// CurrentLSB = 0.0000400 (40µA per bit)
// 5. Compute the calibration register
// Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
// Cal = 10240 (0x2800)
// 6. Calculate the power LSB
// PowerLSB = 20 * CurrentLSB
// PowerLSB = 0.0008 (800µW per bit)
// 7. Compute the maximum current and shunt voltage values before overflow
//
// Max_Current = Current_LSB * 32767
// Max_Current = 1.31068A before overflow
//
// If Max_Current > Max_Possible_I then
// Max_Current_Before_Overflow = MaxPossible_I
// Else
// Max_Current_Before_Overflow = Max_Current
// End If
//
// ... In this case, we're good though since Max_Current is less than MaxPossible_I
//
// Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
// Max_ShuntVoltage = 0.131068V
//
// If Max_ShuntVoltage >= VSHUNT_MAX
// Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX
// Else
// Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage
// End If
// 8. Computer the Maximum Power
// MaximumPower = Max_Current_Before_Overflow * VBUS_MAX
// MaximumPower = 1.31068 * 32V
// MaximumPower = 41.94176W
// Set multipliers to convert raw current/power values
ina219_currentDivider_mA = 25; // Current LSB = 40uA per bit (1000/40 = 25)
ina219_powerDivider_mW = 1; // Power LSB = 800µW per bit
// Set Calibration register to 'Cal' calculated above
ina219WriteRegister(INA219_REG_CALIBRATION, 0x2800);
// Set Config register to take into account the settings above
uint16_t config = INA219_CONFIG_BVOLTAGERANGE_32V |
INA219_CONFIG_GAIN_8_320MV |
INA219_CONFIG_BADCRES_12BIT |
INA219_CONFIG_SADCRES_12BIT_1S_532US |
INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS;
ina219WriteRegister(INA219_REG_CONFIG, config);
}
/**************************************************************************/
/*!
@brief Configures to INA219 to be able to measure up to 16V and 500mA
of current. Each unit of current corresponds to 25uA, and each
unit of power corresponds to 500µW. Counter overflow occurs at
800mA.
@note These calculations assume a 0.1 ohm resistor is present
*/
/**************************************************************************/
void ina219SetCalibration_16V_500mA(void)
{
// VBUS_MAX = 16V
// VSHUNT_MAX = 0.08 (Assumes Gain 2, 80mV, can also be 0.32, 0.16, 0.04)
// RSHUNT = 0.1 (Resistor value in ohms)
// 1. Determine max possible current
// MaxPossible_I = VSHUNT_MAX / RSHUNT
// MaxPossible_I = 0.8A
// 2. Determine max expected current
// MaxExpected_I = 0.5A
// 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
// MinimumLSB = MaxExpected_I/32767
// MinimumLSB = 0.0000153 (15.3µA per bit)
// MaximumLSB = MaxExpected_I/4096
// MaximumLSB = 0.0001221 (122µA per bit)
// 4. Choose an LSB between the min and max values
// (Preferrably a roundish number close to MinLSB)
// CurrentLSB = 0.0000250 (25µA per bit)
// 5. Compute the calibration register
// Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
// Cal = 16384 (0x4000)
// 6. Calculate the power LSB
// PowerLSB = 20 * CurrentLSB
// PowerLSB = 0.0005 (500µW per bit)
// 7. Compute the maximum current and shunt voltage values before overflow
//
// Max_Current = Current_LSB * 32767
// Max_Current = 0.819175 (819 mA before overflow)
//
// If Max_Current > Max_Possible_I then
// Max_Current_Before_Overflow = MaxPossible_I
// Else
// Max_Current_Before_Overflow = Max_Current
// End If
//
// Max_Current_Before_Overflow = 0.8A
//
// Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
// Max_ShuntVoltage = 0.8 * 0.1
// Max_ShuntVoltage = 0.08V
//
// If Max_ShuntVoltage >= VSHUNT_MAX
// Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX
// Else
// Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage
// End If
// 8. Computer the Maximum Power
// MaximumPower = Max_Current_Before_Overflow * VBUS_MAX
// MaximumPower = 0.8 * 16V
// MaximumPower = 12.8W
// Set multipliers to convert raw current/power values
ina219_currentDivider_mA = 40; // Current LSB = 25uA per bit (1000/25 = 40)
ina219_powerDivider_mW = 1; // Power LSB = 500µW per bit
// Set Calibration register to 'Cal' calculated above
ina219WriteRegister(INA219_REG_CALIBRATION, 0x4000);
// Set Config register to take into account the settings above
uint16_t config = INA219_CONFIG_BVOLTAGERANGE_16V |
INA219_CONFIG_GAIN_2_80MV |
INA219_CONFIG_BADCRES_12BIT |
INA219_CONFIG_SADCRES_12BIT_1S_532US |
INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS;
ina219WriteRegister(INA219_REG_CONFIG, config);
}
/**************************************************************************/
/*!
@brief Configures to INA219 to be able to measure up to 16V and 200mA
of current. Each unit of current corresponds to 10uA, and each
unit of power corresponds to 200µW. Counter overflow occurs at
327mA.
@note These calculations assume a 0.1 ohm resistor is present
*/
/**************************************************************************/
void ina219SetCalibration_16V_200mA(void)
{
// VBUS_MAX = 16V
// VSHUNT_MAX = 0.04 (Assumes Gain 1, 40mV, can also be 0.32, 0.16, 0.08)
// RSHUNT = 0.1 (Resistor value in ohms)
// 1. Determine max possible current
// MaxPossible_I = VSHUNT_MAX / RSHUNT
// MaxPossible_I = 0.4A
// 2. Determine max expected current
// MaxExpected_I = 0.2A
// 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
// MinimumLSB = MaxExpected_I/32767
// MinimumLSB = 0.000006104 (6.104µA per bit)
// MaximumLSB = MaxExpected_I/4096
// MaximumLSB = 0,000048828 (48.82µA per bit)
// 4. Choose an LSB between the min and max values
// CurrentLSB = 0.000010 (10µA per bit)
// 5. Compute the calibration register
// Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
// Cal = 40960 (0xA000)
// 6. Calculate the power LSB
// PowerLSB = 20 * CurrentLSB
// PowerLSB = 0.0002 (200µW per bit)
// 7. Compute the maximum current and shunt voltage values before overflow
//
// Max_Current = Current_LSB * 32767
// Max_Current = 0.32767 (328 mA before overflow)
//
// If Max_Current > Max_Possible_I then
// Max_Current_Before_Overflow = MaxPossible_I
// Else
// Max_Current_Before_Overflow = Max_Current
// End If
//
// Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
// Max_ShuntVoltage = 0.032767V
//
// If Max_ShuntVoltage >= VSHUNT_MAX
// Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX
// Else
// Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage
// End If
// 8. Computer the Maximum Power
// MaximumPower = Max_Current_Before_Overflow * VBUS_MAX
// MaximumPower = 0.32767 * 16V
// MaximumPower = 5.24W
// Set multipliers to convert raw current/power values
ina219_currentDivider_mA = 100; // Current LSB = 10uA per bit (1000/10 = 100)
ina219_powerDivider_mW = 1; // Power LSB = 200µW per bit
// Set Calibration register to 'Cal' calculated above
ina219WriteRegister(INA219_REG_CALIBRATION, 0xA000);
// Set Config register to take into account the settings above
uint16_t config = INA219_CONFIG_BVOLTAGERANGE_16V |
INA219_CONFIG_GAIN_1_40MV |
INA219_CONFIG_BADCRES_12BIT |
INA219_CONFIG_SADCRES_12BIT_1S_532US |
INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS;
ina219WriteRegister(INA219_REG_CONFIG, config);
}
/**************************************************************************/
/*!
@brief Initialises the I2C block
*/
/**************************************************************************/
int ina219Init(void)
{
int RET = RET_OK;
uint16_t ReadBack;
// Reset INA219 (set to default values)
RET = ina219WriteRegister(INA219_REG_CONFIG, INA219_CONFIG_RESET);
ina219Read16(INA219_REG_CONFIG,&ReadBack);
if(ReadBack != INA219_CONFIG_RESET_READBACK)
{
return RET_ERROR;
}
// Setup chip for 32V and 2A by default
// ina219SetCalibration_32V_2A();
ina219SetCalibration_13V_10A();
return RET;
}
/**************************************************************************/
/*!
@brief Gets the shunt voltage (16-bit signed integer, so +-32767)
*/
/**************************************************************************/
int16_t ina219GetShuntVoltage(void)
{
uint16_t value;
ina219Read16(INA219_REG_SHUNTVOLTAGE, &value);
return value;
}
/**************************************************************************/
/*!
@brief Gets the shunt voltage (16-bit signed integer, so +-32767)
*/
/**************************************************************************/
int16_t ina219GetBusVoltage(void)
{
uint16_t value;
ina219Read16(INA219_REG_BUSVOLTAGE, &value);
// Shift to the right 3 to drop CNVR and OVF and then multiply by LSB
return (value >> 3) * 4;
}
/**************************************************************************/
/*!
@brief Gets the raw power value (16-bit signed integer, so +-32767)
*/
/**************************************************************************/
int16_t ina219GetPower(void)
{
uint16_t value;
ina219Read16(INA219_REG_POWER, &value);
return value;
}
/**************************************************************************/
/*!
@brief Gets the power value in mW, taking into account the config
settings and power LSB
*/
/**************************************************************************/
int16_t ina219GetPower_mW(void)
{
uint16_t value;
ina219Read16(INA219_REG_POWER, &value);
return value / ina219_powerDivider_mW;
}
/**************************************************************************/
/*!
@brief Gets the raw current value (16-bit signed integer, so +-32767)
*/
/**************************************************************************/
int16_t ina219GetCurrent(void)
{
uint16_t value;
ina219Read16(INA219_REG_CURRENT, &value);
return value;
}
/**************************************************************************/
/*!
@brief Gets the current value in mA, taking into account the
config settings and current LSB
*/
/**************************************************************************/
int16_t ina219GetCurrent_mA(void)
{
uint16_t value;
ina219Read16(INA219_REG_CURRENT, &value);
return value / ina219_currentDivider_mA;
}

View File

@ -0,0 +1,141 @@
/**************************************************************************/
/*!
@file ina219.h
@author K. Townsend (microBuilder.eu)
@section LICENSE
Software License Agreement (BSD License)
Copyright (c) 2012 Kevin Townsend
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/
#ifndef _INA219_H_
#define _INS219_H_
#include "define.h"
//#include "projectconfig.h"
//#include "core/i2c/i2c.h"
/*=========================================================================
I2C ADDRESS/BITS
-----------------------------------------------------------------------*/
#define INA219_ADDRESS (0x80) // 1000000x (A0+A1=GND)
#define INA219_READ (0x01)
/*=========================================================================*/
/*=========================================================================
CONFIG REGISTER (R/W)
-----------------------------------------------------------------------*/
#define INA219_REG_CONFIG (0x00)
/*---------------------------------------------------------------------*/
#define INA219_CONFIG_RESET (0x8000) // Reset Bit
#define INA219_CONFIG_RESET_READBACK 0x39FF
#define INA219_CONFIG_BVOLTAGERANGE_MASK (0x4000) // Bus Voltage Range Mask
#define INA219_CONFIG_BVOLTAGERANGE_16V (0x0000) // 0-16V Range
#define INA219_CONFIG_BVOLTAGERANGE_32V (0x4000) // 0-32V Range
#define INA219_CONFIG_GAIN_MASK (0x1800) // Gain Mask
#define INA219_CONFIG_GAIN_1_40MV (0x0000) // Gain 1, 40mV Range
#define INA219_CONFIG_GAIN_2_80MV (0x0800) // Gain 2, 80mV Range
#define INA219_CONFIG_GAIN_4_160MV (0x1000) // Gain 4, 160mV Range
#define INA219_CONFIG_GAIN_8_320MV (0x1800) // Gain 8, 320mV Range
#define INA219_CONFIG_BADCRES_MASK (0x0780) // Bus ADC Resolution Mask
#define INA219_CONFIG_BADCRES_9BIT (0x0080) // 9-bit bus res = 0..511
#define INA219_CONFIG_BADCRES_10BIT (0x0100) // 10-bit bus res = 0..1023
#define INA219_CONFIG_BADCRES_11BIT (0x0200) // 11-bit bus res = 0..2047
#define INA219_CONFIG_BADCRES_12BIT (0x0400) // 12-bit bus res = 0..4097
#define INA219_CONFIG_SADCRES_MASK (0x0078) // Shunt ADC Resolution and Averaging Mask
#define INA219_CONFIG_SADCRES_9BIT_1S_84US (0x0000) // 1 x 9-bit shunt sample
#define INA219_CONFIG_SADCRES_10BIT_1S_148US (0x0008) // 1 x 10-bit shunt sample
#define INA219_CONFIG_SADCRES_11BIT_1S_276US (0x0010) // 1 x 11-bit shunt sample
#define INA219_CONFIG_SADCRES_12BIT_1S_532US (0x0018) // 1 x 12-bit shunt sample
#define INA219_CONFIG_SADCRES_12BIT_2S_1060US (0x0048) // 2 x 12-bit shunt samples averaged together
#define INA219_CONFIG_SADCRES_12BIT_4S_2130US (0x0050) // 4 x 12-bit shunt samples averaged together
#define INA219_CONFIG_SADCRES_12BIT_8S_4260US (0x0058) // 8 x 12-bit shunt samples averaged together
#define INA219_CONFIG_SADCRES_12BIT_16S_8510US (0x0060) // 16 x 12-bit shunt samples averaged together
#define INA219_CONFIG_SADCRES_12BIT_32S_17MS (0x0068) // 32 x 12-bit shunt samples averaged together
#define INA219_CONFIG_SADCRES_12BIT_64S_34MS (0x0070) // 64 x 12-bit shunt samples averaged together
#define INA219_CONFIG_SADCRES_12BIT_128S_69MS (0x0078) // 128 x 12-bit shunt samples averaged together
#define INA219_CONFIG_MODE_MASK (0x0007) // Operating Mode Mask
#define INA219_CONFIG_MODE_POWERDOWN (0x0000)
#define INA219_CONFIG_MODE_SVOLT_TRIGGERED (0x0001)
#define INA219_CONFIG_MODE_BVOLT_TRIGGERED (0x0002)
#define INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED (0x0003)
#define INA219_CONFIG_MODE_ADCOFF (0x0004)
#define INA219_CONFIG_MODE_SVOLT_CONTINUOUS (0x0005)
#define INA219_CONFIG_MODE_BVOLT_CONTINUOUS (0x0006)
#define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS (0x0007)
/*=========================================================================*/
/*=========================================================================
SHUNT VOLTAGE REGISTER (R)
-----------------------------------------------------------------------*/
#define INA219_REG_SHUNTVOLTAGE (0x01)
/*=========================================================================*/
/*=========================================================================
BUS VOLTAGE REGISTER (R)
-----------------------------------------------------------------------*/
#define INA219_REG_BUSVOLTAGE (0x02)
/*=========================================================================*/
/*=========================================================================
POWER REGISTER (R)
-----------------------------------------------------------------------*/
#define INA219_REG_POWER (0x03)
/*=========================================================================*/
/*=========================================================================
CURRENT REGISTER (R)
-----------------------------------------------------------------------*/
#define INA219_REG_CURRENT (0x04)
/*=========================================================================*/
/*=========================================================================
CALIBRATION REGISTER (R/W)
-----------------------------------------------------------------------*/
#define INA219_REG_CALIBRATION (0x05)
/*=========================================================================*/
int ina219Init(void);
int16_t ina219GetShuntVoltage(void);
int16_t ina219GetBusVoltage(void);
int16_t ina219GetPower(void);
int16_t ina219GetPower_mW(void);
int16_t ina219GetCurrent(void);
int16_t ina219GetCurrent_mA(void);
#endif

View File

@ -0,0 +1,75 @@
/******************************************************************************/
/* Files to Include */
/******************************************************************************/
#include <plib.h> /* Include to use PIC32 peripheral libraries */
#include <sys/attribs.h> /* For __ISR definition */
#include <stdint.h> /* For uint32_t definition */
#include <stdbool.h> /* For true/false definition */
/******************************************************************************/
/* Interrupt Vector Options */
/******************************************************************************/
/* */
/* VECTOR NAMES: */
/* */
/* _CORE_TIMER_VECTOR _COMPARATOR_2_VECTOR */
/* _CORE_SOFTWARE_0_VECTOR _UART_2A_VECTOR */
/* _CORE_SOFTWARE_1_VECTOR _I2C_2A_VECTOR */
/* _EXTERNAL_0_VECTOR _SPI_2_VECTOR */
/* _TIMER_1_VECTOR _SPI_2A_VECTOR */
/* _INPUT_CAPTURE_1_VECTOR _I2C_4_VECTOR */
/* _OUTPUT_COMPARE_1_VECTOR _UART_3_VECTOR */
/* _EXTERNAL_1_VECTOR _UART_2_VECTOR */
/* _TIMER_2_VECTOR _SPI_3A_VECTOR */
/* _INPUT_CAPTURE_2_VECTOR _I2C_3A_VECTOR */
/* _OUTPUT_COMPARE_2_VECTOR _UART_3A_VECTOR */
/* _EXTERNAL_2_VECTOR _SPI_4_VECTOR */
/* _TIMER_3_VECTOR _I2C_5_VECTOR */
/* _INPUT_CAPTURE_3_VECTOR _I2C_2_VECTOR */
/* _OUTPUT_COMPARE_3_VECTOR _FAIL_SAFE_MONITOR_VECTOR */
/* _EXTERNAL_3_VECTOR _RTCC_VECTOR */
/* _TIMER_4_VECTOR _DMA_0_VECTOR */
/* _INPUT_CAPTURE_4_VECTOR _DMA_1_VECTOR */
/* _OUTPUT_COMPARE_4_VECTOR _DMA_2_VECTOR */
/* _EXTERNAL_4_VECTOR _DMA_3_VECTOR */
/* _TIMER_5_VECTOR _DMA_4_VECTOR */
/* _INPUT_CAPTURE_5_VECTOR _DMA_5_VECTOR */
/* _OUTPUT_COMPARE_5_VECTOR _DMA_6_VECTOR */
/* _SPI_1_VECTOR _DMA_7_VECTOR */
/* _I2C_3_VECTOR _FCE_VECTOR */
/* _UART_1A_VECTOR _USB_1_VECTOR */
/* _UART_1_VECTOR _CAN_1_VECTOR */
/* _SPI_1A_VECTOR _CAN_2_VECTOR */
/* _I2C_1A_VECTOR _ETH_VECTOR */
/* _SPI_3_VECTOR _UART_4_VECTOR */
/* _I2C_1_VECTOR _UART_1B_VECTOR */
/* _CHANGE_NOTICE_VECTOR _UART_6_VECTOR */
/* _ADC_VECTOR _UART_2B_VECTOR */
/* _PMP_VECTOR _UART_5_VECTOR */
/* _COMPARATOR_1_VECTOR _UART_3B_VECTOR */
/* */
/* Refer to the device specific .h file in the C32 Compiler */
/* pic32mx\include\proc directory for a complete Vector and IRQ mnemonic */
/* listings for the PIC32 device. */
/* */
/* PRIORITY OPTIONS: */
/* */
/* (default) IPL0AUTO, IPL1, IPL2, ... IPL7 (highest) */
/* */
/* Example Shorthand Syntax */
/* */
/* void __ISR(<Vector Name>,<PRIORITY>) user_interrupt_routine_name(void) */
/* { */
/* <Clear Interrupt Flag> */
/* } */
/* */
/* For more interrupt macro examples refer to the C compiler User Guide in */
/* the C compiler /doc directory. */
/* */
/******************************************************************************/
/* Interrupt Routines */
/******************************************************************************/
/* TODO Add interrupt routine code here. */

View File

@ -0,0 +1,239 @@
/*
Description:
This is a template file for standard C header file.
*/
/* ************************************************************************** */
/* Revision:
### 20120515 JFM
Original version.
### YYYYMMDD Initial, Bug Identification
Change description.
*/
//JFM WINC TODO
#include "define.h"
#include "Uart.h"
#include "BoardCfg.h"
#include "timer.h"
#include "Watchdog.h"
//#include "PWMCtrl.h"
//#include "KnobEncoderCtrl.h"
//#include "LedLightCtrl.h"
//#include "PrintfServer.h"
//#include "MasterCtrlInterface.h"
//#include "SDCardMgr.h"
//#include "FatFS/ff.h"
#include "main.h"
#include "NetworkProtocol.h"
#include "ChaletPowerRelay.h"
#include "BatteryMonitor.h"
#include "CurrentSensor.h"
#include "I2C.h"
#include "SPI_Flash.h"
#include "TemperatureSensor.h"
#include "LoraWatchdog.h"
#include "BootloaderInterface.h"
//#define NO_WIFI
#ifndef NO_WIFI
#include "Terminal.h"
#include "WiFiCtrl.h"
#include "InternalUart.h"
#endif
#ifdef USE_PRINTF
void _mon_putc(char c); //override from stdio to redirect stdout on uart 3B
#elif defined USE_SYSLOG
#include "Syslog.h"
void _mon_putc(char c); //override from stdio to redirect stdout on uart 3B
#endif
#define HEARTBEAT_LED_TIMEOUT 400
#define VOLTS_PER_BITS (float)3.3/1023
static void InitializeBoard(void);
#pragma config FPLLMUL = MUL_20, FPLLIDIV = DIV_2, FPLLODIV = DIV_1, FWDTEN = OFF, WDTPS = PS4096 //Watchdog timeout = 4,096s
#pragma config POSCMOD = EC, FNOSC = PRIPLL, FPBDIV = DIV_1
//#pragma config POSCMOD = XT, FNOSC = PRIPLL, FPBDIV = DIV_1
#pragma config ICESEL = ICS_PGx2, BWP = OFF
#pragma config FSOSCEN = OFF
int main(void)
{
int mRetCode = 1;
SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE); //Use peripheral library to optimize configuration
INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);// configure for multi-vectored mode interrupts
OSCCONbits.SOSCEN = 0;
#ifndef __32MX330F064H__
AD1PCFG = 0xFFFF; //Sart with I/O pins configured as digital I/O
#endif
InitBoard();
INTEnableInterrupts();
TimerInit();
InitWatchdog();
// I2CInit();
InitChaletPowerRelay();
InitBatteryMonitor();
InitHarakiriRelay();
InitTempSensor();
InitUart();
ProtocolInit();
InitLoraWatchdog();
InitSPIFlash();
#ifdef USE_SYSLOG
InitSyslog();
#endif
printf("ChaletDuino V2 Initialized\n");
SPIFlashCheckAndConfigure();
TempSensorCheckAndConfigure();
BootloaderInterfaceInit();
// SPIFlashErase64KSector(0x180000,1);
//
// unsigned char test[100];
// int i = 0;
//
// for(i = 0; i < 100; i++)
// {
// test[i] = i;
// }
//
//
// SPIFlashWriteBuffer(test,100,0x180000);
//
// for(i = 0; i < 100; i++)
// {
// test[i] = 0;
// }
//
// SPIFlashReadBuffer(test,100,0x180000);
//
#ifndef NO_WIFI
InitTerminal();
InitWiFi();
#endif
// unsigned int bw;
// FRESULT res;
// res = f_mount(&FatFs, "", 0); /* Give a work area to the default drive */
// if(!res)
// {
// printf("Could not mount SD card\n");
// }
// else
// {
// printf("SD Card mounted successfuly");
// }
//
// if (f_open(&File[0], "newfile.txt", FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) /* Create a file */
//// {
//
// res = f_write(&File[0], "It works!\r\n", 11, &bw); /* Write data to the file */
//
// res = f_close(&File[0]); /* Close the file */
//
// }
// int res = OpenPrintfServer();
TimerStart(HEARTBEAT_LED_TMR,HEARTBEAT_LED_TIMEOUT);
// printf("Lora Monitor Started\n");
printf("test %d\n", 1);
EnableWatchdog();
KickWatchdog();
mRetCode = 1;
while(mRetCode == 1)
{
KickWatchdog();
#ifndef NO_WIFI
TickWiFi();
#endif
TickTerminal();
UartTick();
ChaletPowerRelayTick();
BatteryMonitorTick();
SyslogTick();
TickTempSensor();
BootloaderInterfaceTick();
TickLoraWatchdog();
if(IsTimerExpired(HEARTBEAT_LED_TMR))
{
HEARTBEAT_LED_2_PIN = ~HEARTBEAT_LED_2_PIN;
TimerStart(HEARTBEAT_LED_TMR,HEARTBEAT_LED_TIMEOUT);
}
}
return mRetCode;
}
void InitializeBoard()
{
InitBoard();
}
#ifdef USE_PRINTF
void _mon_putc(char c)
{
U2TXREG = c;
while (U2STAbits.TRMT==0);
}
#elif defined USE_SYSLOG
void _mon_putc(char c)
{
SyslogNewByte(c);
}
#endif
//EOF

View File

@ -0,0 +1,165 @@
/**
* \file
*
* \brief MAIN configuration.
*
* Copyright (c) 2015 - 2018 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
#ifndef MAIN_H_INCLUDED
#define MAIN_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
//#include "driver/include/m2m_wifi.h"
//
//// <<< 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 "WINC1500_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 server IP address 1 <0-255>
//// <id> app_ip_address_1
//#ifndef DHCP_IP_ADDRESS_1
//#define DHCP_IP_ADDRESS_1 192
//#endif
//
//// <o> DHCP server IP address 2 <0-255>
//// <id> app_ip_address_2
//#ifndef DHCP_IP_ADDRESS_2
//#define DHCP_IP_ADDRESS_2 168
//#endif
//
//// <o> DHCP server IP address 3 <0-255>
//// <id> app_ip_address_3
//#ifndef DHCP_IP_ADDRESS_3
//#define DHCP_IP_ADDRESS_3 1
//#endif
//
//// <o> DHCP server IP address 4 <0-255>
//// <id> app_ip_address_4
//#ifndef DHCP_IP_ADDRESS_4
//#define DHCP_IP_ADDRESS_4 1
//#endif
////</h>
//// <<< end of configuration section >>>
//
///** Using broadcast address for simplicity. */
//#define MAIN_SERVER_PORT (80)
//
///** Using IP address. */
//#define IPV4_BYTE(val, index) ((val >> (index * 8)) & 0xFF)
//
///** Send buffer of TCP socket. */
//#define MAIN_PREFIX_BUFFER "GET /data/2.5/weather?q="
//#define MAIN_POST_BUFFER \
// "&mode=xml&units=metric&appid=c592e14137c3471fa9627b44f6649db4 HTTP/1.1\r\nHost: " \
// "api.openweathermap.org\r\nAccept: */*\r\n\r\n"
///** Weather information provider server. */
//#define MAIN_WEATHER_SERVER_NAME "openweathermap.org"
//
///** Input City Name. */
//#define MAIN_CITY_NAME "london"
//
///** Receive buffer size. */
//#define MAIN_WIFI_M2M_BUFFER_SIZE 1024
//
//#define MAIN_M2M_DHCP_SERVER_IP \
// { \
// DHCP_IP_ADDRESS_1, DHCP_IP_ADDRESS_2, DHCP_IP_ADDRESS_3, DHCP_IP_ADDRESS_4 \
// }
//#define MAIN_HTTP_PROV_SERVER_DOMAIN_NAME "atmel.com"
//
//#define MAIN_MAC_ADDRESS \
// { \
// 0xf8, 0xf0, 0x05, 0x45, 0xD4, 0x84 \
// }
//
//#define MAIN_HEX2ASCII(x) (((x) >= 10) ? (((x)-10) + 'A') : ((x) + '0'))
//
//#define TEMPERATURE_ABS(a) (((a) > 0) ? (a) : -(a))
//
//static tstrM2MAPConfig gstrM2MAPConfig = {MAIN_M2M_SSID,
// 1,
// 0,
// sizeof(MAIN_M2M_AP_KEY) - 1,
// MAIN_M2M_AP_KEY,
// MAIN_M2M_AP_SEC,
// MAIN_M2M_AP_SSID_MODE,
// MAIN_M2M_DHCP_SERVER_IP};
//
//static CONST char gacHttpProvDomainName[] = MAIN_HTTP_PROV_SERVER_DOMAIN_NAME;
//
//static uint8 gau8MacAddr[] = MAIN_MAC_ADDRESS;
//static sint8 gacDeviceName[] = MAIN_M2M_SSID;
//
//#define MAIN_WAITING_TIME 3000
//#define MAIN_RETRY_COUNT 10
#ifdef __cplusplus
}
#endif
#endif /* MAIN_H_INCLUDED */

View File

@ -0,0 +1,20 @@
/******************************************************************************/
/* Files to Include */
/******************************************************************************/
#include <plib.h> /* Include to use PIC32 peripheral libraries */
#include <stdint.h> /* For uint32_t definition */
#include <stdbool.h> /* For true/false definition */
#include "system.h" /* variables/params used by system.c */
/******************************************************************************/
/* System Level Functions */
/* */
/* Custom oscillator configuration funtions, reset source evaluation */
/* functions, and other non-peripheral microcontroller initialization */
/* functions get placed in system.c */
/* */
/******************************************************************************/
/* <Initialize variables in system.h and put code for system algorithms here.>*/

View File

@ -0,0 +1,19 @@
/******************************************************************************/
/* System Level #define Macros */
/******************************************************************************/
/* TODO Define system operating frequency */
/* Microcontroller MIPs (FCY) */
#define SYS_FREQ 80000000L
#define FCY SYS_FREQ
/******************************************************************************/
/* System Function Prototypes */
/******************************************************************************/
/* Custom oscillator configuration funtions, reset source evaluation
functions, and other non-peripheral microcontroller initialization functions
go here. */

Some files were not shown because too many files have changed in this diff Show More