First commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
*.o
|
||||
*.d
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* File: BoardCfg.h
|
||||
* Author: JF
|
||||
*
|
||||
* Created on November 26, 2018, 4:50 PM
|
||||
*/
|
||||
|
||||
#ifndef BOARDCFG_H
|
||||
#define BOARDCFG_H
|
||||
|
||||
#include "define.h"
|
||||
|
||||
static inline __attribute__((always_inline)) unsigned char SPICalculateBRG(unsigned int pb_clk, unsigned int spi_clk)
|
||||
{
|
||||
unsigned int brg;
|
||||
|
||||
brg = pb_clk / (2 * spi_clk);
|
||||
|
||||
if(pb_clk % (2 * spi_clk))
|
||||
brg++;
|
||||
|
||||
if(brg > 0x100)
|
||||
brg = 0x100;
|
||||
|
||||
if(brg)
|
||||
brg--;
|
||||
|
||||
return (unsigned char) brg;
|
||||
}
|
||||
//
|
||||
#ifdef FUBARINO_BRD
|
||||
#include "BoardCfg_Fubarino.h"
|
||||
#endif
|
||||
|
||||
//#ifdef PINGUINO_BRD
|
||||
//#include "BoardCfg_Pinguino.h"
|
||||
//#endif
|
||||
|
||||
#ifdef CHALETDUINO_BRD
|
||||
#include "BoardCfg_Chaletduino.h"
|
||||
#endif
|
||||
|
||||
#ifdef CHALETDUINO_V2_BRD
|
||||
#include "BoardCfg_ChaletduinoV2.h"
|
||||
#endif
|
||||
int InitBoard();
|
||||
|
||||
#endif /* BOARDCFG_H */
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* File: DigitalIO_Chaletduino.h
|
||||
* Author: JF
|
||||
*
|
||||
* Created on November 24, 2018, 3:20 PM
|
||||
*/
|
||||
|
||||
#ifndef DIGITALIO_CHALETDUINO_H
|
||||
#define DIGITALIO_CHALETDUINO_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Includes */
|
||||
#include "define.h"
|
||||
/* ************************************************************************** */
|
||||
/* Defines */
|
||||
//#include <plib.h>
|
||||
#define SYS_FREQ (80000000L) //Clock period = 12.5 ns
|
||||
#define PERIPHERAL_FREQ (80000000L)
|
||||
|
||||
|
||||
|
||||
//Output pins hardware definitions
|
||||
//
|
||||
#define HEARTBEAT_LED_2_PIN_DIR TRISEbits.TRISE6
|
||||
#define HEARTBEAT_LED_2_PIN LATEbits.LATE6
|
||||
#define HEARTBEAT_LED_2_TOGGLE_REG LATEINV
|
||||
#define HEARTBEAT_LED_2_SET_REG LATESET
|
||||
#define HEARTBEAT_LED_2_CLEAR_REG LATECLR
|
||||
#define HEARTBEAT_LED_2_TOGGLE_MASK _LATG_LATE6_MASK
|
||||
|
||||
#define HEARTBEAT_LED_1_PIN_DIR TRISEbits.TRISE5
|
||||
#define HEARTBEAT_LED_1_PIN LATEbits.LATE5
|
||||
#define HEARTBEAT_LED_1_TOGGLE_REG LATEINV
|
||||
#define HEARTBEAT_LED_1_SET_REG LATESET
|
||||
#define HEARTBEAT_LED_1_CLEAR_REG LATECLR
|
||||
#define HEARTBEAT_LED_1_TOGGLE_MASK _LATE_LATE5_MASK
|
||||
|
||||
#define LORA_ACTIVITY_LED_PIN_DIR TRISFbits.TRISF1
|
||||
#define LORA_ACTIVITY_LED_PIN LATFbits.LATF1
|
||||
#define LORA_ACTIVITY_LED_TOGGLE_REG LATFINV
|
||||
#define LORA_ACTIVITY_LED_SET_REG LATFSET
|
||||
#define LORA_ACTIVITY_LED_CLEAR_REG LATFCLR
|
||||
#define LORA_ACTIVITY_LED_TOGGLE_MASK _LATE_LATF1_MASK
|
||||
|
||||
// #define GP_DEBUG_1_PIN_DIR TRISEbits.TRISE5
|
||||
// #define GP_DEBUG_1_PIN LATEbits.LATE5
|
||||
// #define GP_DEBUG_2_PIN_DIR TRISEbits.TRISE6
|
||||
// #define GP_DEBUG_2_PIN LATEbits.LATE6
|
||||
|
||||
|
||||
// #define SD_CARD_DETECT_PIN_DIR TRISDbits.TRISD8
|
||||
// #define SD_CARD_DETECT_PIN LATDbits.LATD8
|
||||
|
||||
//SPI port defs
|
||||
#define SPI_SDO_PIN_DIR TRISGbits.TRISG8
|
||||
#define SPI_SDI_PIN_DIR TRISGbits.TRISG7
|
||||
#define SPI_SCK_PIN_DIR TRISGbits.TRISG6
|
||||
|
||||
//SD Card
|
||||
#define SD_SPI_SS_PIN_DIR TRISBbits.TRISB13
|
||||
#define SD_SPI_SS_PIN LATBbits.LATB13
|
||||
|
||||
//SPI Flash
|
||||
#define FLASH_SS_PIN_DIR TRISEbits.TRISE3
|
||||
#define FLASH_SS_PIN LATEbits.LATE3
|
||||
|
||||
|
||||
//Wifi (WINC3400 module)
|
||||
#define WIFI_SPI_SS_PIN_DIR TRISEbits.TRISE0
|
||||
#define WIFI_SPI_SS_PIN LATEbits.LATE0
|
||||
#define WIFI_IRQ_PIN_DIR TRISDbits.TRISD0
|
||||
#define WIFI_IRQ_PIN PORTDbits.RD0
|
||||
|
||||
// #define WIFI_SPI_CFG_PIN_DIR TRISEbits.TRISE1
|
||||
// #define WIFI_SPI_CFG_PIN LATEbits.LATE1
|
||||
#define WIFI_CHP_EN_PIN_DIR TRISEbits.TRISE2
|
||||
#define WIFI_CHP_EN_PIN LATEbits.LATE2
|
||||
#define WIFI_CHP_RST_PIN_DIR TRISEbits.TRISE4
|
||||
#define WIFI_CHP_RST_PIN LATEbits.LATE4
|
||||
|
||||
//Chalet power relay
|
||||
#define POWER_RELAY_ON_PIN_DIR TRISEbits.TRISE7
|
||||
#define POWER_RELAY_ON_PIN LATEbits.LATE7 //X2-3
|
||||
#define POWER_RELAY_OFF_PIN_DIR TRISGbits.TRISG9
|
||||
#define POWER_RELAY_OFF_PIN LATGbits.LATG9 //X3-5
|
||||
|
||||
//Harakiri relay
|
||||
#define HARAKIRI_RELAY_ON_PIN_DIR TRISBbits.TRISB0
|
||||
#define HARAKIRI_RELAY_ON_PIN LATBbits.LATB0 //X2-3
|
||||
|
||||
//12V presence detection input
|
||||
#define CHALET_12V_PRESENCE_PIN_DIR TRISBbits.TRISB15
|
||||
#define CHALET_12V_PRESENCE_PIN PORTBbits.RB15 //X2-3
|
||||
|
||||
//Battery voltage measurement (analog input)
|
||||
#define BATTERY_VOLTAGE_ANALOG_PIN_DIR TRISBbits.TRISB1
|
||||
|
||||
//Current sensor. Those pins tristate is controlled by the I2C module
|
||||
#define CURRENT_MODULE_I2C_SCL_PIN_DIR TRISDbits.TRISD3
|
||||
#define CURRENT_MODULE_I2C_SDA_PIN_DIR TRISDbits.TRISD2
|
||||
|
||||
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Prototypes */
|
||||
void InitDigitalIO(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DIGITALIO_PINGUINO_H */
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* File: DigitalIO_Chaletduino.h
|
||||
* Author: JF
|
||||
*
|
||||
* Created on November 24, 2018, 3:20 PM
|
||||
*/
|
||||
|
||||
#ifndef DIGITALIO_CHALETDUINO_H
|
||||
#define DIGITALIO_CHALETDUINO_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Includes */
|
||||
#include "define.h"
|
||||
/* ************************************************************************** */
|
||||
/* Defines */
|
||||
//#include <plib.h>
|
||||
#define SYS_FREQ (80000000L) //Clock period = 12.5 ns
|
||||
#define PERIPHERAL_FREQ (80000000L)
|
||||
|
||||
|
||||
|
||||
//Output pins hardware definitions
|
||||
//
|
||||
#define HEARTBEAT_LED_2_PIN_DIR TRISEbits.TRISE6
|
||||
#define HEARTBEAT_LED_2_PIN LATEbits.LATE6
|
||||
#define HEARTBEAT_LED_2_TOGGLE_REG LATEINV
|
||||
#define HEARTBEAT_LED_2_SET_REG LATESET
|
||||
#define HEARTBEAT_LED_2_CLEAR_REG LATECLR
|
||||
#define HEARTBEAT_LED_2_TOGGLE_MASK _LATG_LATE6_MASK
|
||||
|
||||
#define HEARTBEAT_LED_1_PIN_DIR TRISEbits.TRISE5
|
||||
#define HEARTBEAT_LED_1_PIN LATEbits.LATE5
|
||||
#define HEARTBEAT_LED_1_TOGGLE_REG LATEINV
|
||||
#define HEARTBEAT_LED_1_SET_REG LATESET
|
||||
#define HEARTBEAT_LED_1_CLEAR_REG LATECLR
|
||||
#define HEARTBEAT_LED_1_TOGGLE_MASK _LATE_LATE5_MASK
|
||||
|
||||
//#define LORA_ACTIVITY_LED_PIN_DIR TRISFbits.TRISF1
|
||||
//#define LORA_ACTIVITY_LED_PIN LATFbits.LATF1
|
||||
//#define LORA_ACTIVITY_LED_TOGGLE_REG LATFINV
|
||||
//#define LORA_ACTIVITY_LED_SET_REG LATFSET
|
||||
//#define LORA_ACTIVITY_LED_CLEAR_REG LATFCLR
|
||||
//#define LORA_ACTIVITY_LED_TOGGLE_MASK _LATE_LATF1_MASK
|
||||
|
||||
// #define GP_DEBUG_1_PIN_DIR TRISEbits.TRISE5
|
||||
// #define GP_DEBUG_1_PIN LATEbits.LATE5
|
||||
// #define GP_DEBUG_2_PIN_DIR TRISEbits.TRISE6
|
||||
// #define GP_DEBUG_2_PIN LATEbits.LATE6
|
||||
|
||||
|
||||
// #define SD_CARD_DETECT_PIN_DIR TRISDbits.TRISD8
|
||||
// #define SD_CARD_DETECT_PIN LATDbits.LATD8
|
||||
|
||||
//SPI port defs
|
||||
#define SPI_SDO_PIN_DIR TRISGbits.TRISG8
|
||||
#define SPI_SDI_PIN_DIR TRISGbits.TRISG7
|
||||
#define SPI_SCK_PIN_DIR TRISGbits.TRISG6
|
||||
|
||||
|
||||
|
||||
|
||||
//SD Card
|
||||
#define SD_SPI_SS_PIN_DIR TRISBbits.TRISB13
|
||||
#define SD_SPI_SS_PIN LATBbits.LATB13
|
||||
|
||||
//SPI Flash
|
||||
#define FLASH_SS_PIN_DIR TRISEbits.TRISE3
|
||||
#define FLASH_SS_PIN LATEbits.LATE3
|
||||
|
||||
|
||||
//Wifi (WINC3400 module)
|
||||
#define WIFI_SPI_SS_PIN_DIR TRISEbits.TRISE0
|
||||
#define WIFI_SPI_SS_PIN LATEbits.LATE0
|
||||
#define WIFI_IRQ_PIN_DIR TRISDbits.TRISD0
|
||||
#define WIFI_IRQ_PIN PORTDbits.RD0
|
||||
|
||||
// #define WIFI_SPI_CFG_PIN_DIR TRISEbits.TRISE1
|
||||
// #define WIFI_SPI_CFG_PIN LATEbits.LATE1
|
||||
#define WIFI_CHP_EN_PIN_DIR TRISEbits.TRISE2
|
||||
#define WIFI_CHP_EN_PIN LATEbits.LATE2
|
||||
#define WIFI_CHP_RST_PIN_DIR TRISEbits.TRISE4
|
||||
#define WIFI_CHP_RST_PIN LATEbits.LATE4
|
||||
|
||||
//Chalet power relay
|
||||
#define POWER_RELAY_ON_PIN_DIR TRISEbits.TRISE7
|
||||
#define POWER_RELAY_ON_PIN LATEbits.LATE7 //X2-
|
||||
#define POWER_RELAY_OFF_PIN_DIR TRISGbits.TRISG9
|
||||
#define POWER_RELAY_OFF_PIN LATGbits.LATG9 //X3-
|
||||
|
||||
//Harakiri relay
|
||||
#define HARAKIRI_RELAY_ON_PIN_DIR TRISDbits.TRISD6
|
||||
#define HARAKIRI_RELAY_ON_PIN LATDbits.LATD6
|
||||
|
||||
//12V presence detection input
|
||||
#define CHALET_12V_PRESENCE_PIN_DIR TRISBbits.TRISB15
|
||||
#define CHALET_12V_PRESENCE_PIN PORTBbits.RB15 //X2-
|
||||
|
||||
//Battery voltage measurement (analog input)
|
||||
#define BATTERY_VOLTAGE_ANALOG_PIN_DIR TRISBbits.TRISB1 //X2-7
|
||||
|
||||
// //Current sensor. Those pins tristate is controlled by the I2C module
|
||||
//#define CURRENT_MODULE_I2C_SCL_PIN_DIR TRISDbits.TRISD3
|
||||
//#define CURRENT_MODULE_I2C_SDA_PIN_DIR TRISDbits.TRISD2
|
||||
|
||||
//Onboard temperature sensor (SPI)
|
||||
#define TEMP_SENSOR_CS_PIN_DIR TRISDbits.TRISD4
|
||||
#define TEMP_SENSOR_CS_PIN LATDbits.LATD4
|
||||
#define TEMP_SENSOR_SPI_SDO_PIN_DIR TRISDbits.TRISD3
|
||||
#define TEMP_SENSOR_SPI_SDI_PIN_DIR TRISDbits.TRISD2
|
||||
#define TEMP_SENSOR_SPI_SCK_PIN_DIR TRISDbits.TRISD1
|
||||
|
||||
|
||||
//Analog (Hall effect) current sensor
|
||||
#define CURRENT_SENSOR_IN1_PIN_DIR TRISBbits.TRISB2
|
||||
#define CURRENT_SENSOR_IN2_PIN_DIR TRISBbits.TRISB0
|
||||
|
||||
//LoRa
|
||||
#define LORA_MODULE_RELAY_PIN_DIR TRISDbits.TRISD11
|
||||
#define LORA_MODULE_RELAY_PIN LATDbits.LATD11
|
||||
#define LORA_MODULE_M0_PIN_DIR TRISDbits.TRISD3 //V2
|
||||
#define LORA_MODULE_M0_PIN LATDbits.LATD3
|
||||
#define LORA_MODULE_M1_PIN_DIR TRISDbits.TRISD9
|
||||
#define LORA_MODULE_M1_PIN LATDbits.LATD9
|
||||
#define LORA_MODULE_INT_PIN_DIR TRISDbits.TRISD8
|
||||
#define LORA_MODULE_INT_PIN PORTDbits.RD8
|
||||
//#define LORA_MODULE_RX_LED_PIN_DIR TRISCbits.TRISC14
|
||||
//#define LORA_MODULE_RX_LED_PIN LATCbits.LATC14
|
||||
//#define LORA_MODULE_TX_LED_PIN_DIR TRISCbits.TRISC13
|
||||
//#define LORA_MODULE_TX_LED_PIN LATCbits.LATC13
|
||||
#define LORA_MODULE_RX_LED_PIN_DIR TRISBbits.TRISB4
|
||||
#define LORA_MODULE_RX_LED_PIN LATBbits.LATB4
|
||||
#define LORA_MODULE_TX_LED_PIN_DIR TRISFbits.TRISF1
|
||||
#define LORA_MODULE_TX_LED_PIN LATFbits.LATF1
|
||||
|
||||
|
||||
//LCD Screen
|
||||
#define LCD_RS_PIN_DIR TRISDbits.TRISD5
|
||||
#define LCD_RS_PIN LATDbits.LATD5
|
||||
#define LCD_RW_PIN_DIR TRISBbits.TRISB13
|
||||
#define LCD_RW_PIN LATBbits.LATB13
|
||||
#define LCD_E_PIN_DIR TRISBbits.TRISB12
|
||||
#define LCD_E_PIN LATBbits.LATB12
|
||||
#define LCD_DB4_PIN_DIR TRISBbits.TRISB3
|
||||
#define LCD_DB4_PIN LATBbits.LATB3
|
||||
#define LCD_DB5_PIN_DIR TRISBbits.TRISB9
|
||||
#define LCD_DB5_PIN LATBbits.LATB9
|
||||
#define LCD_DB6_PIN_DIR TRISBbits.TRISB10
|
||||
#define LCD_DB6_PIN LATBbits.LATB10
|
||||
#define LCD_DB7_PIN_DIR TRISBbits.TRISB11
|
||||
#define LCD_DB7_PIN LATBbits.LATB11
|
||||
#define LCD_SCROLL_BTN_PIN_DIR TRISBbits.TRISB5
|
||||
#define LCD_SCROLL_BTN_PIN PORTBbits.RB5
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Prototypes */
|
||||
void InitDigitalIO(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DIGITALIO_PINGUINO_H */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -0,0 +1,427 @@
|
||||
/**********************************************************************
|
||||
Project: Automatic cat feeder
|
||||
Date: march 19 2006
|
||||
Author: Jean-Fran�ois Martel
|
||||
Target: PIC 18F252
|
||||
Compiler: Microchip mcc18
|
||||
Filename: Protocol.c
|
||||
|
||||
File description: Communication protocol implementation.
|
||||
|
||||
|
||||
jean-francois.martel@polymtl.ca
|
||||
**********************************************************************/
|
||||
#include "define.h"
|
||||
#include <string.h>
|
||||
#include "ProtocolDefs.h"
|
||||
#include "BootloaderProtocol.h"
|
||||
#include "BootloaderInterface.h"
|
||||
#include "WiFiCtrl.h"
|
||||
#include "checksum.h"
|
||||
|
||||
|
||||
//test
|
||||
unsigned int BootloaderHeader = 0;
|
||||
unsigned int BootloaderDataSize = 0;
|
||||
unsigned int BootloaderDataCtr = 0;
|
||||
unsigned int BootloaderBufPtr = 0;
|
||||
unsigned int BootloaderCRC = 0;
|
||||
unsigned int BtldrComputedCRC = CRC_START_32;
|
||||
unsigned char *BootloaderRxPtr;
|
||||
unsigned char BootloaderCommand = 0;
|
||||
unsigned char BootloaderState = RxHeader1;
|
||||
const unsigned char *BootloaderDataStartPtr = &BootloaderBuffer[9];
|
||||
|
||||
|
||||
static char MyDeviceID = ID_SPRINKLER_DEVICE;
|
||||
|
||||
void BootloaderProtocolInit(void)
|
||||
{
|
||||
BootloaderProtocolResetStateMachine();
|
||||
|
||||
}
|
||||
|
||||
void BootloaderProtocolStateMachine(unsigned char Data)
|
||||
{
|
||||
switch(BootloaderState)
|
||||
{
|
||||
case Initialization: //Reset all pointers and data...
|
||||
{
|
||||
BootloaderDataSize = 0;
|
||||
BootloaderBufPtr = 0;
|
||||
BootloaderCommand = 0;
|
||||
BootloaderCRC = 0;
|
||||
BootloaderState = RxHeader1;
|
||||
BtldrComputedCRC = CRC_START_32;
|
||||
break;
|
||||
}
|
||||
case RxHeader1: //Wait for data header...
|
||||
{
|
||||
BootloaderHeader <<= 8;
|
||||
BootloaderHeader += Data; //0xDE
|
||||
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
|
||||
|
||||
if(Data == BOOTLOADER_FRAME_HEADER_1)
|
||||
{
|
||||
BootloaderState = RxHeader2;
|
||||
}
|
||||
else
|
||||
{
|
||||
BootloaderProtocolResetStateMachine();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RxHeader2: //Wait for data header...
|
||||
{
|
||||
BootloaderHeader <<= 8;
|
||||
BootloaderHeader += Data; //0xAD
|
||||
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
|
||||
|
||||
if(Data == BOOTLOADER_FRAME_HEADER_2)
|
||||
{
|
||||
BootloaderState = RxHeader3;
|
||||
}
|
||||
else
|
||||
{
|
||||
BootloaderProtocolResetStateMachine();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RxHeader3: //Wait for data header...
|
||||
{
|
||||
BootloaderHeader <<= 8;
|
||||
BootloaderHeader += Data; //0xBE
|
||||
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
|
||||
|
||||
if(Data == BOOTLOADER_FRAME_HEADER_3)
|
||||
{
|
||||
BootloaderState = RxHeader4;
|
||||
}
|
||||
else
|
||||
{
|
||||
BootloaderProtocolResetStateMachine();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RxHeader4: //Wait for data header...
|
||||
{
|
||||
BootloaderHeader <<= 8;
|
||||
BootloaderHeader += Data; //0xEF
|
||||
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
|
||||
|
||||
if(BootloaderHeader != BOOTLOADER_FRAME_HEADER)
|
||||
{
|
||||
//TODO, send NACK?
|
||||
BootloaderProtocolResetStateMachine();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
BootloaderState = RxCmd;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case RxCmd:
|
||||
{
|
||||
BootloaderCommand = Data;
|
||||
BootloaderState = RxPayloadSize1;
|
||||
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
|
||||
break;
|
||||
}
|
||||
case RxPayloadSize1:
|
||||
{
|
||||
BootloaderDataSize = Data;
|
||||
BootloaderState = RxPayloadSize2;
|
||||
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
|
||||
break;
|
||||
}
|
||||
case RxPayloadSize2:
|
||||
{
|
||||
BootloaderDataSize <<= 8;
|
||||
BootloaderDataSize += Data;
|
||||
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
|
||||
|
||||
BootloaderState = RxPayloadSize3;
|
||||
break;
|
||||
}
|
||||
case RxPayloadSize3:
|
||||
{
|
||||
BootloaderDataSize <<= 8;
|
||||
BootloaderDataSize += Data;
|
||||
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
|
||||
|
||||
BootloaderState = RxPayloadSize4;
|
||||
break;
|
||||
}
|
||||
case RxPayloadSize4:
|
||||
{
|
||||
BootloaderDataSize <<= 8;
|
||||
BootloaderDataSize += Data;
|
||||
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
|
||||
|
||||
if(BootloaderDataSize > MAX_BOOTLOADER_PAYLOAD_SIZE+8) //+8 bytes for the size and index data
|
||||
{
|
||||
//TODO, send NACK?
|
||||
BootloaderProtocolResetStateMachine();
|
||||
break;
|
||||
}
|
||||
|
||||
if(BootloaderDataSize == 0)
|
||||
{
|
||||
BootloaderState = RxCRC1;
|
||||
}
|
||||
else
|
||||
{
|
||||
BootloaderState = RxPayload;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RxPayload: //Data size
|
||||
{
|
||||
*BootloaderRxPtr = Data;
|
||||
BootloaderRxPtr++;
|
||||
|
||||
BootloaderDataCtr++;
|
||||
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
|
||||
|
||||
if(BootloaderDataCtr == BootloaderDataSize)
|
||||
{
|
||||
BootloaderState = RxCRC1;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case RxCRC1: //Data size
|
||||
{
|
||||
BootloaderCRC = Data;
|
||||
BootloaderState = RxCRC2;
|
||||
break;
|
||||
}
|
||||
case RxCRC2: //Data size
|
||||
{
|
||||
BootloaderCRC <<= 8;
|
||||
BootloaderCRC += Data;
|
||||
BootloaderState = RxCRC3;
|
||||
break;
|
||||
}
|
||||
case RxCRC3: //Data size
|
||||
{
|
||||
BootloaderCRC <<= 8;
|
||||
BootloaderCRC += Data;
|
||||
BootloaderState = RxCRC4;
|
||||
break;
|
||||
}
|
||||
case RxCRC4: //Data size
|
||||
{
|
||||
BootloaderCRC <<= 8;
|
||||
BootloaderCRC += Data;
|
||||
|
||||
//TODO: Compute and Compare CRC.
|
||||
|
||||
BtldrComputedCRC ^= 0xffffffffL;
|
||||
//if(BootloaderCRC != 0xBAADCAFE)
|
||||
if(BootloaderCRC != BtldrComputedCRC)
|
||||
{
|
||||
BootloaderExecuteCmd(BootloaderCommand,0);
|
||||
BootloaderProtocolResetStateMachine();
|
||||
return;
|
||||
}
|
||||
|
||||
BootloaderExecuteCmd(BootloaderCommand,1);
|
||||
BootloaderProtocolResetStateMachine();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
BootloaderProtocolResetStateMachine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BootloaderProtocolProtocolAnalyzeNewData(unsigned char *DataBuf, int size)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
BootloaderProtocolStateMachine(*DataBuf++);
|
||||
}
|
||||
}
|
||||
|
||||
void BootloaderProtocolResetStateMachine()
|
||||
{
|
||||
BootloaderDataSize = 0;
|
||||
BootloaderHeader = 0;
|
||||
BootloaderBufPtr = 0;
|
||||
BootloaderCommand = 0;
|
||||
BootloaderCRC = 0;
|
||||
BootloaderState = RxHeader1;
|
||||
BootloaderDataCtr = 0;
|
||||
BtldrComputedCRC = CRC_START_32;
|
||||
BootloaderRxPtr = &BootloaderBuffer[0];
|
||||
}
|
||||
|
||||
void BootloaderProtocolSendFrame(unsigned char Cmd, int Size)
|
||||
{
|
||||
//Header
|
||||
BootloaderBuffer[0] = BOOTLOADER_FRAME_HEADER_1; //Header
|
||||
BootloaderBuffer[1] = BOOTLOADER_FRAME_HEADER_2;
|
||||
BootloaderBuffer[2] = BOOTLOADER_FRAME_HEADER_3;
|
||||
BootloaderBuffer[3] = BOOTLOADER_FRAME_HEADER_4;
|
||||
|
||||
BootloaderBuffer[4] = Cmd;
|
||||
|
||||
char nibble = (char)((Size >> 24) &0x000000FF);
|
||||
BootloaderBuffer[5] = nibble;
|
||||
|
||||
nibble = (char)((Size >> 16) &0x000000FF);
|
||||
BootloaderBuffer[6] = nibble;
|
||||
|
||||
nibble = (char)((Size >> 8) &0x000000FF);
|
||||
BootloaderBuffer[7] = nibble;
|
||||
|
||||
nibble = (char)(Size &0x000000FF);
|
||||
BootloaderBuffer[8] = nibble;
|
||||
|
||||
unsigned int CRC = CRC_START_32;
|
||||
CRC = crc_32((const unsigned char*)BootloaderBuffer,Size+9);
|
||||
|
||||
unsigned char* CRCPtr = (unsigned char*)BootloaderDataStartPtr + Size;
|
||||
|
||||
nibble = (char)((CRC >> 24) &0x000000FF);
|
||||
*CRCPtr++ = nibble;
|
||||
|
||||
nibble = (char)((CRC >> 16) &0x000000FF);
|
||||
*CRCPtr++ = nibble;
|
||||
|
||||
nibble = (char)((CRC >> 8) &0x000000FF);
|
||||
*CRCPtr++ = nibble;
|
||||
|
||||
nibble = (char)(CRC &0x000000FF);
|
||||
*CRCPtr++ = nibble;
|
||||
|
||||
// *CRCPtr++ = 0xBA;
|
||||
// *CRCPtr++ = 0xAD;
|
||||
// *CRCPtr++ = 0xCA;
|
||||
// *CRCPtr++ = 0xFE;
|
||||
|
||||
SendBootloaderData(&BootloaderBuffer[0],Size + PROTOCOL_INFO_DATA_SIZE);
|
||||
}
|
||||
|
||||
unsigned char *BootloaderProtocolGetDataBufferPtr()
|
||||
{
|
||||
return (unsigned char*)BootloaderDataStartPtr;
|
||||
}
|
||||
|
||||
void BootloaderProtocolSendHeartbeat()
|
||||
{
|
||||
*BootloaderProtocolGetDataBufferPtr() = BOOTLOADER_ACK;
|
||||
BootloaderProtocolSendFrame(BOOTLOADER_HEARTBEAT_RESPONSE,1);
|
||||
}
|
||||
|
||||
void BootloaderProtocolSendACK(unsigned char Cmd)
|
||||
{
|
||||
*BootloaderProtocolGetDataBufferPtr() = BOOTLOADER_ACK;
|
||||
BootloaderProtocolSendFrame(Cmd,1);
|
||||
}
|
||||
|
||||
void BootloaderProtocolSendNACK(unsigned char Cmd)
|
||||
{
|
||||
*BootloaderProtocolGetDataBufferPtr() = 0;
|
||||
BootloaderProtocolSendFrame(Cmd,1);
|
||||
}
|
||||
|
||||
void BootloaderProtocolSendInitUploadResponse(char result)
|
||||
{
|
||||
int MaxSize = MAX_BOOTLOADER_PAYLOAD_SIZE;
|
||||
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
|
||||
|
||||
*DataPtr++ = result;
|
||||
if(result == 1)
|
||||
{
|
||||
char nibble = (char)((MaxSize >> 24) &0x000000FF);
|
||||
*DataPtr++ = nibble;
|
||||
|
||||
nibble = (char)((MaxSize >> 16) &0x000000FF);
|
||||
*DataPtr++ = nibble;
|
||||
|
||||
nibble = (char)((MaxSize >> 8) &0x000000FF);
|
||||
*DataPtr++ = nibble;
|
||||
|
||||
nibble = (char)(MaxSize &0x000000FF);
|
||||
*DataPtr++ = nibble;
|
||||
}
|
||||
else
|
||||
{
|
||||
*DataPtr++ = 0;
|
||||
*DataPtr++ = 0;
|
||||
*DataPtr++ = 0;
|
||||
*DataPtr++ = 0;
|
||||
}
|
||||
|
||||
BootloaderProtocolSendFrame(BOOTLOADER_INIT_UPLOAD_RESPONSE,5);
|
||||
}
|
||||
|
||||
void BootloaderProtocolSendDataChunkResult(char ErrorCode, int ChunkValue)
|
||||
{
|
||||
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
|
||||
|
||||
*DataPtr++ = ErrorCode;
|
||||
|
||||
char nibble = (char)((ChunkValue >> 24) &0x000000FF);
|
||||
*DataPtr++ = nibble;
|
||||
|
||||
nibble = (char)((ChunkValue >> 16) &0x000000FF);
|
||||
*DataPtr++ = nibble;
|
||||
|
||||
nibble = (char)((ChunkValue >> 8) &0x000000FF);
|
||||
*DataPtr++ = nibble;
|
||||
|
||||
nibble = (char)(ChunkValue &0x000000FF);
|
||||
*DataPtr++ = nibble;
|
||||
|
||||
BootloaderProtocolSendFrame(BOOTLOADER_SEND_DATA_CHUNK_RESPONSE,5);
|
||||
}
|
||||
|
||||
void BootloaderProtocolSendBootloaderState(char State)
|
||||
{
|
||||
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
|
||||
|
||||
*DataPtr++ = State;
|
||||
|
||||
BootloaderProtocolSendFrame(BOOTLOADER_GET_STATE_RESPONSE,1);
|
||||
}
|
||||
|
||||
void BootloaderProtocolSendFirmwareUploadResult(char Result)
|
||||
{
|
||||
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
|
||||
|
||||
*DataPtr++ = Result;
|
||||
|
||||
BootloaderProtocolSendFrame(BOOTLOADER_UPLOAD_FINISHED_RESPONSE,1);
|
||||
}
|
||||
|
||||
void BootloaderProtocolSendFlashCheckResult(char Result)
|
||||
{
|
||||
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
|
||||
|
||||
*DataPtr++ = Result;
|
||||
|
||||
BootloaderProtocolSendFrame(BOOTLOADER_CHECK_FLASH_FIRMW_INTEGRITY_RESPONSE,1);
|
||||
}
|
||||
|
||||
void BootloaderProtocolSendStoredFirmwareInfoResponse(unsigned char* FirmwareData, int size)
|
||||
{
|
||||
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
|
||||
|
||||
int i = 0;
|
||||
for(i = 0; i < size; i++)
|
||||
{
|
||||
*DataPtr++ = *FirmwareData++;
|
||||
}
|
||||
|
||||
|
||||
BootloaderProtocolSendFrame(BOOTLOADER_GET_STORED_FIRMWARE_INFO_RESPONSE,size);
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/**********************************************************************
|
||||
Project: Automatic cat feeder
|
||||
Date: march 19 2006
|
||||
Author: Jean-Fran�ois Martel
|
||||
Target: PIC 18F252
|
||||
Compiler: Microchip mcc18
|
||||
Filename: Protocol.h
|
||||
|
||||
File description: Communication protocol implementation.
|
||||
|
||||
|
||||
jean-francois.martel@polymtl.ca
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
#ifndef BOOTLOADERPROTOCOL_H
|
||||
#define BOOTLOADERPROTOCOL_H
|
||||
|
||||
//Protocol buffer specific definitions
|
||||
|
||||
#define MAX_BOOTLOADER_PAYLOAD_SIZE 150
|
||||
#define BOOTLOADER_FRAME_HEADER 0xDEADBEEF
|
||||
#define BOOTLOADER_FRAME_HEADER_1 0xDE
|
||||
#define BOOTLOADER_FRAME_HEADER_2 0xAD
|
||||
#define BOOTLOADER_FRAME_HEADER_3 0xBE
|
||||
#define BOOTLOADER_FRAME_HEADER_4 0xEF
|
||||
#define PROTOCOL_INFO_DATA_SIZE 13 //Header + Cmd + Size + CRC = 13 bytes
|
||||
//State Machine states
|
||||
enum States
|
||||
{
|
||||
Initialization,
|
||||
RxHeader1,
|
||||
RxHeader2,
|
||||
RxHeader3,
|
||||
RxHeader4,
|
||||
RxCmd,
|
||||
RxPayloadSize1,
|
||||
RxPayloadSize2,
|
||||
RxPayloadSize3,
|
||||
RxPayloadSize4,
|
||||
RxPayload,
|
||||
RxCRC1,
|
||||
RxCRC2,
|
||||
RxCRC3,
|
||||
RxCRC4
|
||||
};
|
||||
|
||||
enum eBootloaderProtocolDataTransferError
|
||||
{
|
||||
BOOTLOADER_CHUNK_TRANSFER_SUCCESS = 1,
|
||||
BOOTLOADER_CHUNK_TRANSFER_ERROR_RESEND = 2,
|
||||
BOOTLOADER_CHUNK_TRANSFER_ERROR_FLASH_FAILURE = 3,
|
||||
BOOTLOADER_CHUNK_TRANSFER_ERROR_INVALID_CHUNK_INDEX = 4,
|
||||
BOOTLOADER_CHUNK_TRANSFER_ERROR_FLASH_ERROR = 5,
|
||||
|
||||
BOOTLOADER_CHUNK_TRANSFER_MAX_ERROR
|
||||
};
|
||||
|
||||
enum eBootloaderProtocolInitTransferError
|
||||
{
|
||||
BOOTLOADEDR_INIT_TRANSFER_ERROR = 0,
|
||||
BOOTLOADEDR_INIT_TRANSFER_OK = 1,
|
||||
BOOTLOADEDR_INIT_TRANSFER_ERROR_FLASH_NOT_ERASED,
|
||||
|
||||
BOOTLOADEDR_INIT_TRANSFER_MAX_ERROR
|
||||
};
|
||||
|
||||
enum eBootloaderUploadResult
|
||||
{
|
||||
BOOTLOADER_UPLOAD_FAILED_UNKNOWN_ERROR = 0,
|
||||
BOOTLOADER_UPLOAD_SUCCESS = 1,
|
||||
BOOTLOADER_UPLOAD_FAILED_FLASH_VERIFICATION_ERROR = 2,
|
||||
|
||||
BOOTLOADER_UPLOAD_MAX_ERROR
|
||||
};
|
||||
|
||||
enum eFlashCheckResult
|
||||
{
|
||||
FLASH_CHECK_FAILED = 0,
|
||||
FLASH_CHECK_SUCCESS = 1,
|
||||
|
||||
FLASH_CHECK_MAX_RESULT
|
||||
};
|
||||
|
||||
//enum DEVICES_IDS
|
||||
//{
|
||||
// ID_MASTER, //Master Controller
|
||||
// ID_CONSOLE, //LCD Console
|
||||
// ID_PC, //PC
|
||||
// ID_AV_MUX, //Audio Video Multiplexer
|
||||
// ID_IR_REMOTE,
|
||||
// ID_DEADBOLT
|
||||
//};
|
||||
|
||||
//enum MESSAGE_IDS
|
||||
//{
|
||||
// TX_NETWORK_ACK = 1,
|
||||
// RX_GET_STATUS,
|
||||
// TX_DEADBOLT_STATUS,
|
||||
//
|
||||
// MAX_NETWORK_CMD
|
||||
//};
|
||||
|
||||
//State machine states definition
|
||||
|
||||
void BootloaderProtocolInit(void);
|
||||
void BootloaderProtocolStateMachine(unsigned char STATE);
|
||||
void BootloaderProtocolResetStateMachine(void);
|
||||
void BootloaderProtocolProtocolAnalyzeNewData(unsigned char *DataBuf, int size);
|
||||
void BootloaderProtocolSendFrame(unsigned char Cmd, int size);
|
||||
unsigned char *BootloaderProtocolGetDataBufferPtr();
|
||||
|
||||
void BootloaderProtocolSendHeartbeat();
|
||||
void BootloaderProtocolSendACK(unsigned char Cmd);
|
||||
void BootloaderProtocolSendNACK(unsigned char Cmd);
|
||||
void BootloaderProtocolSendInitUploadResponse(char result);
|
||||
void BootloaderProtocolSendDataChunkResult(char ErrorCode, int ChunkValue);
|
||||
void BootloaderProtocolSendBootloaderState(char State);
|
||||
void BootloaderProtocolSendFirmwareUploadResult(char Result);
|
||||
void BootloaderProtocolSendFlashCheckResult(char Result);
|
||||
void BootloaderProtocolSendStoredFirmwareInfoResponse(unsigned char* FirmwareData, int size);
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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 ---*/
|
||||
@@ -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
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "BoardCfg.h"
|
||||
|
||||
int InitBoard()
|
||||
{
|
||||
return RET_OK;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* File: LedLightCtrl.h
|
||||
* Author: JF
|
||||
*
|
||||
* Created on November 30, 2018, 8:09 PM
|
||||
*/
|
||||
|
||||
#ifndef LEDLIGHTCTRL_H
|
||||
#define LEDLIGHTCTRL_H
|
||||
|
||||
#define LED_LIGHT_TICK_STEP 5 //Percent
|
||||
#define LED_LIGHT_MIN_DIM_VAL 10 //Percent
|
||||
|
||||
#define LED_LIGHT_ON 1
|
||||
#define LED_LIGHT_OFF 0
|
||||
|
||||
extern int LedLightBrightness;
|
||||
|
||||
void LedLightDim(int Percent);
|
||||
void LedLightDecrease();
|
||||
void LedLightBright(int Percent);
|
||||
void LedLightIncrease();
|
||||
void LedLightSet(int Percent);
|
||||
|
||||
void LedLightONOFFBtnPressed();
|
||||
void TurnLedLightON();
|
||||
void TurnLedLightOFF();
|
||||
|
||||
int GetLedLightBrightness();
|
||||
int GetLedLightState();
|
||||
|
||||
#endif /* LEDLIGHTCTRL_H */
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
#include "LoraNetworkInterface.h"
|
||||
#include "ProtocolDefs.h"
|
||||
#include "NetworkProtocol.h"
|
||||
#include "InternalUart.h"
|
||||
#include "define.h"
|
||||
#include "BoardCfg.h"
|
||||
#include "Uart.h"
|
||||
#include "ChaletPowerRelay.h"
|
||||
#include "HarakiriRelay.h"
|
||||
#include "BatteryMonitor.h"
|
||||
#include "LedLightCtrl.h"
|
||||
#include "TemperatureSensor.h"
|
||||
#include "SPI_Flash.h"
|
||||
#include "FlashMapping.h"
|
||||
#include "LoraWatchdog.h"
|
||||
#include "versionbuild.h"
|
||||
//#include "WiFiCtrl.h"
|
||||
//
|
||||
|
||||
//enum eWiFiState
|
||||
//{
|
||||
// WIFI_MODULE_OFF_STATE = 0,
|
||||
// WIFI_CONNECTED_STATE,
|
||||
// WIFI_DISCONNECTED_STATE,
|
||||
// WIFI_INIT_ERROR_STATE,
|
||||
// WIFI_UNKNOWN_STATE
|
||||
//};
|
||||
unsigned char mLoraPreamble[3]={0x00,LORA_MASTER_ADDRESS,LORA_CHANNEL};
|
||||
|
||||
static const char mFirmwareVersion[15] = VERSIONNUMBER;
|
||||
unsigned int mTotalMasterNbRequests = 0;
|
||||
|
||||
void ExecuteMasterCommand(int Command, unsigned char *Data)
|
||||
{
|
||||
//Whatever was the command, we are online...
|
||||
LORA_MODULE_RX_LED_PIN = LED_OFF;
|
||||
KickLoraWatchdog();
|
||||
// printf("EXEC\n\n");
|
||||
ChaletPowerRelayKickTimer();
|
||||
mTotalMasterNbRequests++;
|
||||
switch(Command)
|
||||
{
|
||||
case CHALET_INTERFACE_ACK:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CHALET_GENERAL_STATUS_REQUEST:
|
||||
{
|
||||
float FloatVoltage = GetBatteryVoltage();
|
||||
float FloatTemperature = TempSensorGetTemp();
|
||||
unsigned int BattVoltage = *((int*)&FloatVoltage);
|
||||
unsigned int Temperature = *((int*)&FloatTemperature);
|
||||
int SolarPanelCurrent = GetSolarPanelCurrent();
|
||||
int SOC = GetBatterySOC();
|
||||
|
||||
char GeneralStatus = 0;
|
||||
char ChaletStatus[18];
|
||||
|
||||
if(GetChaletPowerRelayState() == CHALET_POWER_RELAY_ON_STATE)
|
||||
{
|
||||
GeneralStatus |= LORA_CHALET_STATUS_POWER_RELAY_MASK;
|
||||
}
|
||||
if(GetCurrentModuleOK() == true)
|
||||
{
|
||||
GeneralStatus |= LORA_CHALET_STATUS_CUR_SENSOR_MASK;
|
||||
}
|
||||
|
||||
ChaletStatus[0] = GeneralStatus; //General Status
|
||||
ChaletStatus[1] = GetWiFiSate(); //Wifi Module state
|
||||
|
||||
ChaletStatus[2] = (char)(BattVoltage & 0x000000FF); //Battery Voltage 1
|
||||
BattVoltage >>= 8;
|
||||
ChaletStatus[3] = (char)(BattVoltage & 0x000000FF); //Battery Voltage 2
|
||||
BattVoltage >>= 8;
|
||||
ChaletStatus[4] = (char)(BattVoltage & 0x000000FF); //Battery Voltage 3
|
||||
BattVoltage >>= 8;
|
||||
ChaletStatus[5] = (char)(BattVoltage & 0x000000FF); //Battery Voltage 4
|
||||
|
||||
ChaletStatus[6] = (char)(SolarPanelCurrent & 0x000000FF); //Solar panel Current 1
|
||||
SolarPanelCurrent >>= 8;
|
||||
ChaletStatus[7] = (char)(SolarPanelCurrent & 0x000000FF); //Solar panel Current 2
|
||||
|
||||
ChaletStatus[8] = (char)(SOC & 0x000000FF); //Battery SOC 1
|
||||
SolarPanelCurrent >>= 8;
|
||||
ChaletStatus[9] = (char)(SolarPanelCurrent & 0x000000FF); //Battery SOC 2
|
||||
|
||||
ChaletStatus[10] = (char)(Temperature & 0x000000FF); //Temperature 1
|
||||
Temperature >>= 8;
|
||||
ChaletStatus[11] = (char)(Temperature & 0x000000FF); //Temperature 2
|
||||
Temperature >>= 8;
|
||||
ChaletStatus[12] = (char)(Temperature & 0x000000FF); //BTemperature 3
|
||||
Temperature >>= 8;
|
||||
ChaletStatus[13] = (char)(Temperature & 0x000000FF); //Temperature 4
|
||||
|
||||
int tmp = mTotalMasterNbRequests;
|
||||
ChaletStatus[14] = (char)(mTotalMasterNbRequests & 0x000000FF); //Total Nb Requests 1
|
||||
mTotalMasterNbRequests >>= 8;
|
||||
ChaletStatus[15] = (char)(mTotalMasterNbRequests & 0x000000FF); //Total Nb Requests 2
|
||||
mTotalMasterNbRequests >>= 8;
|
||||
ChaletStatus[16] = (char)(mTotalMasterNbRequests & 0x000000FF); //Total Nb Requests 3
|
||||
mTotalMasterNbRequests >>= 8;
|
||||
ChaletStatus[17] = (char)(mTotalMasterNbRequests & 0x000000FF); //Total Nb Requests 4
|
||||
mTotalMasterNbRequests = tmp;
|
||||
|
||||
|
||||
SendLoraNetworkCommand(CHALET_GENERAL_STATUS_RESPONSE,ChaletStatus,18);
|
||||
|
||||
HEARTBEAT_LED_1_PIN = ~HEARTBEAT_LED_1_PIN;
|
||||
|
||||
break;
|
||||
}
|
||||
case CHALET_AC_POWER_STATE_STATUS_REQUEST:
|
||||
{
|
||||
char PowerStatus = GetChaletPowerRelayState();
|
||||
SendLoraNetworkCommand(CHALET_AC_POWER_STATE_STATUS_RESPONSE,&PowerStatus,1);
|
||||
break;
|
||||
}
|
||||
case CHALET_AC_POWER_SET_STATE_REQUEST:
|
||||
{
|
||||
char response = CHALET_POWER_RELAY_UNKNOWN_STATE;
|
||||
if(Data[0] == CHALET_POWER_RELAY_OFF_STATE)
|
||||
{
|
||||
ChaletPowerRelayTurnOff();
|
||||
response = CHALET_POWER_RELAY_OFF_STATE;
|
||||
}
|
||||
else if(Data[0] == CHALET_POWER_RELAY_ON_STATE)
|
||||
{
|
||||
ChaletPowerRelayTurnOn();
|
||||
response = CHALET_POWER_RELAY_ON_STATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//invalid state requested.... don't do anything
|
||||
response = CHALET_POWER_RELAY_UNKNOWN_STATE;
|
||||
}
|
||||
|
||||
SendLoraNetworkCommand(CHALET_AC_POWER_SET_STATE_RESPONSE,&response,1);
|
||||
|
||||
break;
|
||||
}
|
||||
case CHALET_BATTERY_VOLTAGE_REQUEST:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CHALET_WIFI_STATUS_REQUEST:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CHALET_WIFI_SET_STATE_REQUEST:
|
||||
{
|
||||
char response = WIFI_UNKNOWN_STATE;
|
||||
if(Data[0] == 0)
|
||||
{
|
||||
TurnOFFWiFi();
|
||||
response = 0;
|
||||
}
|
||||
else if(Data[0] == 1)
|
||||
{
|
||||
if(GetWiFiSate() != WIFI_CONNECTED_STATE)
|
||||
{
|
||||
InitWiFi();
|
||||
response = GetWiFiSate();
|
||||
}
|
||||
else
|
||||
{
|
||||
response = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//invalid state requested.... don't do anything
|
||||
response = WIFI_UNKNOWN_STATE;
|
||||
}
|
||||
|
||||
SendLoraNetworkCommand(CHALET_WIFI_SET_STATE_RESPONSE,&response,1);
|
||||
break;
|
||||
}
|
||||
case CHALET_DO_HARAKIRI_REQUEST:
|
||||
{
|
||||
char response;
|
||||
if(Data[0] == 0xBA &&
|
||||
Data[1] == 0xAD &&
|
||||
Data[2] == 0xBE &&
|
||||
Data[3] == 0xEF)
|
||||
{
|
||||
//Magic word is OK... let's suicide...
|
||||
response = 0x01;
|
||||
//First, send an ACK to master (this is blocking so it's OK)
|
||||
SendLoraNetworkCommand(CHALET_DO_HARAKIRI_CONFIRMATION,&response,1);
|
||||
HarakiriRelayTurnOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
response = 0x00;
|
||||
SendLoraNetworkCommand(CHALET_DO_HARAKIRI_CONFIRMATION,&response,1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CHALET_REBOOT_CPU_REQUEST:
|
||||
{
|
||||
char response;
|
||||
if(Data[0] == 0xBA &&
|
||||
Data[1] == 0xAD &&
|
||||
Data[2] == 0xCA &&
|
||||
Data[3] == 0xFE)
|
||||
{
|
||||
//Magic word is OK... let's reboot...
|
||||
response = 0x01;
|
||||
//First, send an ACK to master (this is blocking so it's OK)
|
||||
SendLoraNetworkCommandBlocking(CHALET_REBOOT_CPU_RESPONSE,&response,1);
|
||||
Sleep(100);
|
||||
TurnOFFWiFi();
|
||||
Sleep(100);
|
||||
SoftReset();
|
||||
}
|
||||
else
|
||||
{
|
||||
response = 0x00;
|
||||
SendLoraNetworkCommand(CHALET_DO_HARAKIRI_CONFIRMATION,&response,1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CHALET_GET_STORED_WIFI_SETTINGS_REQUEST:
|
||||
{
|
||||
char response[8];
|
||||
SPIFlashReadBuffer(response,8,FLASH_WIFI_IP_ADDRESS);
|
||||
SendLoraNetworkCommand(CHALET_GET_STORED_WIFI_SETTINGS_RESPONSE,response,8);
|
||||
break;
|
||||
}
|
||||
case CHALET_SET_STORED_WIFI_SETTINGS_REQUEST:
|
||||
{
|
||||
char response = 0;
|
||||
if(SPIFlashWriteBuffer(Data,8,FLASH_WIFI_IP_ADDRESS) == 1)
|
||||
{
|
||||
response = 1;
|
||||
}
|
||||
|
||||
SendLoraNetworkCommand(CHALET_SET_STORED_WIFI_SETTINGS_RESPONSE,&response,1);
|
||||
break;
|
||||
}
|
||||
case CHALET_GET_FIRMWARE_VERSION_REQUEST:
|
||||
{
|
||||
SendLoraNetworkCommand(CHALET_GET_FIRMWARE_VERSION_RESPONSE,(unsigned char*)mFirmwareVersion,15);
|
||||
break;
|
||||
}
|
||||
case CHALET_CLEAR_COMMS_STATISTICS_REQUEST:
|
||||
{
|
||||
char response = 1;
|
||||
mTotalMasterNbRequests = 0;
|
||||
SendLoraNetworkCommand(CHALET_CLEAR_COMMS_STATISTICS_RESPONSE,&response,1);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void SendLoraNetworkCommand(int Command, unsigned char *Data, unsigned int DataSize)
|
||||
{
|
||||
unsigned char *Payload;
|
||||
unsigned int PayloadSize;
|
||||
//unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags, int *FrameSize)
|
||||
Payload = ProtocolGetFrame(ID_MASTER,MASTER_ADDRESS,ID_CHALET_DEVICE,Command,Data,DataSize,0,&PayloadSize);
|
||||
|
||||
UartTransmitData(NETWORK_UART_PORT,mLoraPreamble,3);
|
||||
UartTransmitData(NETWORK_UART_PORT,Payload,PayloadSize);
|
||||
|
||||
}
|
||||
|
||||
void SendLoraNetworkCommandBlocking(int Command, unsigned char *Data, unsigned int DataSize)
|
||||
{
|
||||
unsigned char *Payload;
|
||||
unsigned int PayloadSize;
|
||||
//unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags, int *FrameSize)
|
||||
Payload = ProtocolGetFrame(ID_MASTER,MASTER_ADDRESS,ID_CHALET_DEVICE,Command,Data,DataSize,0,&PayloadSize);
|
||||
|
||||
SendInternalUartDataBlocking(mLoraPreamble,3,NETWORK_UART_PORT);
|
||||
SendInternalUartDataBlocking(Payload,PayloadSize,NETWORK_UART_PORT);
|
||||
}
|
||||
|
||||
void TestTx()
|
||||
{
|
||||
char toto = 0x03;
|
||||
SendInternalUartDataBlocking(mLoraPreamble,3,NETWORK_UART_PORT);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
#ifndef LORANEETWORKINTERFACE_H /* Guard against multiple inclusion */
|
||||
#define LORANEETWORKINTERFACE_H
|
||||
#define LORA_CHANNEL 0x04
|
||||
#define LORA_MASTER_ADDRESS 0x05
|
||||
|
||||
#define LORA_CHALET_STATUS_POWER_RELAY_MASK 0x01
|
||||
#define LORA_CHALET_STATUS_CUR_SENSOR_MASK 0x02
|
||||
|
||||
void ExecuteMasterCommand(int Command, unsigned char *Data);
|
||||
void SendLoraNetworkCommand(int Command, unsigned char *Data, unsigned int DataSize);
|
||||
void SendLoraNetworkCommandBlocking(int Command, unsigned char *Data, unsigned int DataSize); //USE WITH CARE
|
||||
|
||||
void TestTx();
|
||||
|
||||
#endif /* LORANEETWORKINTERFACE_H */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
|
||||
#include "define.h"
|
||||
#include "MasterCtrlInterface.h"
|
||||
#ifdef USE_WINC1500
|
||||
#else
|
||||
#include "TCPIP_Stack/TCPIP.h"
|
||||
#endif
|
||||
#include "NetworkProtocol.h"
|
||||
#include "ProtocolDefs.h"
|
||||
#include "timer.h"
|
||||
#include <stdio.h>
|
||||
#include "ValveCtrl.h"
|
||||
#include "FlowMeter.h"
|
||||
|
||||
#ifdef USE_WINC1500
|
||||
#else
|
||||
TCP_SOCKET MySocket;
|
||||
static BYTE MasterIP[] = "192.168.0.100";
|
||||
DWORD MasterPort = 2182;
|
||||
#endif
|
||||
|
||||
int mConnectionState = MASTER_STATE_DISCONNECTED;
|
||||
|
||||
|
||||
int InitMasterCtrlIF()
|
||||
{
|
||||
ProtocolInit();
|
||||
TimerStart(MASTER_CONNECTION_TIMER,MASTER_RECONNECTION_TIMEOUT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ConnectToMasterCtrl()
|
||||
{
|
||||
#ifdef USE_WINC1500
|
||||
#else
|
||||
MySocket = TCPOpen((DWORD) (PTR_BASE) & MasterIP[0], TCP_OPEN_RAM_HOST, MasterPort, TCP_PURPOSE_GENERIC_TCP_CLIENT);
|
||||
|
||||
// Abort operation if no TCP socket of type TCP_PURPOSE_GENERIC_TCP_CLIENT is available
|
||||
// If this ever happens, you need to go add one to TCPIPConfig.h
|
||||
if (MySocket == INVALID_SOCKET)
|
||||
{
|
||||
printf("Could not open socket to MasterCtrl\n");
|
||||
return 0;
|
||||
}
|
||||
printf("MasterCtrl Socket opened\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
void TickMasterCtrlInterface()
|
||||
{
|
||||
#ifdef USE_WINC1500
|
||||
#else
|
||||
WORD Pending = TCPIsGetReady(MySocket);
|
||||
if (Pending != 0)
|
||||
{
|
||||
// printf("Rx %d bytes\n",Pending);
|
||||
int i = 0;
|
||||
for(i = 0; i < Pending; i++)
|
||||
{
|
||||
BYTE Byte;
|
||||
if(TCPGet(MySocket,&Byte) == TRUE)
|
||||
{
|
||||
ProtocolAnalyzeNewData(Byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONNECT_DEVICE_TO_NETWORK
|
||||
if(mConnectionState == MASTER_STATE_DISCONNECTED)
|
||||
{
|
||||
if(IsTimerExpired(MASTER_CONNECTION_TIMER))
|
||||
{
|
||||
TimerStart(MASTER_CONNECTION_TIMER,MASTER_RESPONSE_TIMEOUT);
|
||||
mConnectionState = MASTER_STATE_CONNECTING;
|
||||
ConnectToMasterCtrl();
|
||||
}
|
||||
}
|
||||
else if(mConnectionState == MASTER_STATE_CONNECTING)
|
||||
{
|
||||
// if(IsTimerExpired(MASTER_CONNECTION_TIMER) == true) //
|
||||
// {
|
||||
// TCPClose(MySocket);
|
||||
// TimerStart(MASTER_CONNECTION_TIMER,MASTER_RESPONSE_TIMEOUT);
|
||||
// ConnectToMasterCtrl();
|
||||
// }
|
||||
}
|
||||
else if(mConnectionState == MASTER_STATE_CONNECTED)
|
||||
{
|
||||
// if(IsTimerExpired(MASTER_CONNECTION_TIMER))
|
||||
{
|
||||
if(TCPIsConnected(MySocket) == FALSE)
|
||||
{
|
||||
//we got disconnected...
|
||||
mConnectionState = MASTER_STATE_DISCONNECTED;
|
||||
TCPClose(MySocket);
|
||||
|
||||
printf("Connection with MasterCtrl lost..\n");
|
||||
}
|
||||
TimerStart(MASTER_CONNECTION_TIMER,MASTER_RECONNECTION_TIMEOUT);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void NewMasterMessageReceived(char* Message)
|
||||
{
|
||||
// char Sender = Message[FRAME_SENDER_DEVICE_ID_INDEX];
|
||||
char Target = Message[FRAME_DEST_DEVICE_ID_INDEX];
|
||||
unsigned char Command = Message[FRAME_COMMAND_INDEX];
|
||||
char *Data = &Message[FRAME_DATA_INDEX];
|
||||
|
||||
// printf("MasterMsgReceived %d \n",Command);
|
||||
|
||||
if(Target == ID_ETHERNET_VIRTUAL)
|
||||
{
|
||||
switch(Command)
|
||||
{
|
||||
case ETH_NETWK_DEVICE_INFO_REQUEST:
|
||||
{
|
||||
char Data[2];
|
||||
Data[0] = ID_SPRINKLER_DEVICE;
|
||||
Data[1] = MY_DEVICE_ADDRESS; //Address
|
||||
SendFrame(ID_MASTER,MASTER_ADDRESS,ID_ETHERNET_VIRTUAL, ETH_NETWK_DEVICE_INFO_RESPONSE, Data,2,0);
|
||||
printf("Rx Device info request\n");
|
||||
// int FrameSize = -1;
|
||||
// unsigned char *FramePtr = ProtocolGetFrame(ID_MASTER,MASTER_ADDRESS,ID_ETHERNET_VIRTUAL, ETH_NETWK_DEVICE_INFO_RESPONSE, Data,2,0, &FrameSize);
|
||||
//
|
||||
// if(FrameSize > 0)
|
||||
// {
|
||||
// TCPPutArray(MySocket,FramePtr,FrameSize);
|
||||
// }
|
||||
|
||||
break;
|
||||
}
|
||||
case ETH_NETWK_CONNECTION_REFUSED:
|
||||
{
|
||||
printf("Connection to server refused\n");
|
||||
break;
|
||||
}
|
||||
case ETH_NETWK_SET_DEVICE_INFO_ACK:
|
||||
{
|
||||
//Connected!
|
||||
mConnectionState = MASTER_STATE_CONNECTED;
|
||||
TimerStart(MASTER_CONNECTION_TIMER,MASTER_RECONNECTION_TIMEOUT);
|
||||
printf("Connected to server\n");
|
||||
break;
|
||||
}
|
||||
case ETH_NETWK_DEVICE_INFO_RESPONSE:
|
||||
default:
|
||||
{
|
||||
//error...
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if(Target == ID_SPRINKLER_DEVICE)
|
||||
{
|
||||
switch(Command)
|
||||
{
|
||||
case SPRINKLER_DEVICE_ACK:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case SPRINKLER_DEVICE_STATUS_REQUEST:
|
||||
{
|
||||
unsigned char data[6];
|
||||
data[0] = (unsigned char)GetValveState();
|
||||
GetCurrentFlowBytes(&data[1]);
|
||||
data[3] = 0;
|
||||
data[4] = 0;
|
||||
data[5] = 0;
|
||||
SendFrame(ID_MASTER,MASTER_ADDRESS,ID_SPRINKLER_DEVICE, SPRINKLER_DEVICE_STATUS_RESPONSE, data,6,0);
|
||||
// printf("Status sent\n");
|
||||
break;
|
||||
}
|
||||
case SPRINKLER_DEVICE_SET_SPRINKLER_STATE_REQUEST:
|
||||
{
|
||||
unsigned char *MsgData;
|
||||
char data;
|
||||
|
||||
MsgData = ProtocolMsgDataPtr();
|
||||
if(*MsgData == 1)
|
||||
{
|
||||
SetValve(VALVE_ON);
|
||||
data = 1;
|
||||
}
|
||||
else if(*MsgData == 1)
|
||||
{
|
||||
SetValve(VALVE_OFF);
|
||||
data = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = 0;
|
||||
}
|
||||
|
||||
SendFrame(ID_MASTER,MASTER_ADDRESS,ID_SPRINKLER_DEVICE, SPRINKLER_DEVICE_SET_SPRINKLER_STATE_ACK,&data,1,0);
|
||||
break;
|
||||
}
|
||||
case SPRINKLER_DEVICE_GET_SPRINKLER_STATE_REQUEST:
|
||||
{
|
||||
unsigned char data;
|
||||
data = (unsigned char)GetValveState();
|
||||
SendFrame(ID_MASTER,MASTER_ADDRESS,ID_SPRINKLER_DEVICE, SPRINKLER_DEVICE_GET_SPRINKLER_STATE_RESPONSE,&data,1,0);
|
||||
break;
|
||||
}
|
||||
case SPRINKLER_DEVICE_GET_WATER_FLOW_REQUEST:
|
||||
{
|
||||
unsigned char data[2];
|
||||
GetCurrentFlowBytes(data);
|
||||
SendFrame(ID_MASTER,MASTER_ADDRESS,ID_SPRINKLER_DEVICE, SPRINKLER_DEVICE_GET_WATER_FLOW_RESPONSE,data,2,0);
|
||||
break;
|
||||
}
|
||||
case SPRINKLER_DEVICE_GET_MOISTURE_REQUEST:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case SPRINKLER_DEVICE_SET_PROGRAM_REQUEST:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case SPRINKLER_DEVICE_GET_PROGRAM_REQUEST:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case SPRINKLER_DEVICE_SET_PARAMETERS_REQUEST:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case SPRINKLER_DEVICE_GET_PARAMETERS_REQUEST:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case SPRINKLER_DEVICE_STATUS_RESPONSE:
|
||||
case SPRINKLER_DEVICE_SET_SPRINKLER_STATE_ACK:
|
||||
case SPRINKLER_DEVICE_GET_SPRINKLER_STATE_RESPONSE:
|
||||
case SPRINKLER_DEVICE_GET_WATER_FLOW_RESPONSE:
|
||||
case SPRINKLER_DEVICE_GET_MOISTURE_RESPONSE:
|
||||
case SPRINKLER_DEVICE_SET_PROGRAM_ACK:
|
||||
case SPRINKLER_DEVICE_GET_PROGRAM_RESPONSE:
|
||||
case SPRINKLER_DEVICE_SET_PARAMETERS_ACK:
|
||||
case SPRINKLER_DEVICE_GET_PARAMETERS_RESPONSE:
|
||||
default:
|
||||
{
|
||||
//error
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Ignore..???
|
||||
}
|
||||
}
|
||||
|
||||
bool SendFrame(unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags)
|
||||
{
|
||||
|
||||
int FrameSize = -1;
|
||||
unsigned char *FramePtr = ProtocolGetFrame(DestDevice,DestAddress,SenderDevice, Cmd, Data,Size,Flags,&FrameSize);
|
||||
|
||||
if(FrameSize > 0)
|
||||
{
|
||||
#ifdef USE_WINC1500
|
||||
#else
|
||||
TCPPutArray(MySocket,FramePtr,FrameSize);
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* File: MasterCtrlInterface.h
|
||||
* Author: JF
|
||||
*
|
||||
* Created on March 31, 2017, 2:41 PM
|
||||
*/
|
||||
|
||||
#ifndef MASTERCTRLINTERFACE_H
|
||||
#define MASTERCTRLINTERFACE_H
|
||||
|
||||
enum eMasterConnectionStates
|
||||
{
|
||||
MASTER_STATE_DISCONNECTED,
|
||||
MASTER_STATE_CONNECTING,
|
||||
MASTER_STATE_CONNECTED
|
||||
};
|
||||
|
||||
int InitMasterCtrlIF(void);
|
||||
int ConnectToMasterCtrl(void);
|
||||
void TickMasterCtrlInterface(void);
|
||||
void MasterCtrlSM(int Event);
|
||||
void NewMasterMessageReceived(char* Message);
|
||||
bool SendFrame(unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags);
|
||||
|
||||
|
||||
#endif /* MASTERCTRLINTERFACE_H */
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
/**********************************************************************
|
||||
Project: Automatic cat feeder
|
||||
Date: march 19 2006
|
||||
Author: Jean-Fran�ois Martel
|
||||
Target: PIC 18F252
|
||||
Compiler: Microchip mcc18
|
||||
Filename: Protocol.c
|
||||
|
||||
File description: Communication protocol implementation.
|
||||
|
||||
|
||||
jean-francois.martel@polymtl.ca
|
||||
**********************************************************************/
|
||||
#include "define.h"
|
||||
#include "NetworkProtocol.h"
|
||||
#include "Uart.h"
|
||||
#include <string.h>
|
||||
#include "ProtocolDefs.h"
|
||||
#include "MasterCtrlInterface.h"
|
||||
#include "LoraNetworkInterface.h"
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned char mRxData[MAX_MESSAGE_SIZE+10], mTxData[MAX_MESSAGE_SIZE+10];
|
||||
unsigned int DataSize = 0;
|
||||
unsigned int DataCtr = 0;
|
||||
unsigned int BufPtr = 0;
|
||||
unsigned char RxPtr = 0;
|
||||
unsigned char Command = 0;
|
||||
unsigned char State = RxHeader;
|
||||
unsigned char CRC = 0;
|
||||
unsigned char SenderID = 0;
|
||||
unsigned char SenderAddress = 0;
|
||||
unsigned char Flags = 0;
|
||||
unsigned char IsUpdating = 0;
|
||||
unsigned char *BmpDataPtr = 0;
|
||||
|
||||
static char MyDeviceID = ID_SPRINKLER_DEVICE;
|
||||
|
||||
void ProtocolInit(void)
|
||||
{
|
||||
ResetStateMachine();
|
||||
|
||||
}
|
||||
|
||||
void StateMachine(unsigned char Data)
|
||||
{
|
||||
switch(State)
|
||||
{
|
||||
case Initialization: //Reset all pointers and data...
|
||||
{
|
||||
DataSize = 0;
|
||||
BufPtr = 0;
|
||||
RxPtr = 0;
|
||||
Command = 0;
|
||||
CRC = 0;
|
||||
State = RxHeader;
|
||||
break;
|
||||
}
|
||||
case RxHeader: //Wait for data header...
|
||||
{
|
||||
if(Data == FRAME_HEADER)
|
||||
{
|
||||
mRxData[BufPtr++] = Data;
|
||||
State = RxAdd;
|
||||
CRC ^= Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
DataSize = 0;
|
||||
ResetStateMachine();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case RxAdd: //Sender Address.
|
||||
{
|
||||
SenderAddress = Data;
|
||||
mRxData[BufPtr++] = Data;
|
||||
State = RxID;
|
||||
CRC ^= Data;
|
||||
break;
|
||||
}
|
||||
case RxID: //Sender ID
|
||||
{
|
||||
mRxData[BufPtr++] = Data;
|
||||
State = RxMyID;
|
||||
SenderID = Data;
|
||||
CRC ^= Data;
|
||||
break;
|
||||
}
|
||||
case RxMyID:
|
||||
{
|
||||
// if(Data != MyDeviceID && Data != BROADCAST_VALUE) //Message is not for this type of device and it's not a broadcast
|
||||
// {
|
||||
// ResetStateMachine();
|
||||
// break;
|
||||
// }
|
||||
mRxData[BufPtr++] = Data;
|
||||
State = RxMyAddress;
|
||||
CRC ^= Data;
|
||||
break;
|
||||
}
|
||||
case RxMyAddress:
|
||||
{
|
||||
if(Data != MY_DEVICE_ADDRESS && Data != BROADCAST_VALUE) //Message is not for this device address and it's not a broadcast
|
||||
{
|
||||
ResetStateMachine();
|
||||
break;
|
||||
}
|
||||
mRxData[BufPtr++] = Data;
|
||||
State = RxFlags;
|
||||
CRC ^= Data;
|
||||
break;
|
||||
}
|
||||
case RxFlags:
|
||||
{
|
||||
Flags = Data;
|
||||
mRxData[BufPtr++] = Data;
|
||||
State = RxCMD;
|
||||
CRC ^= Data;
|
||||
break;
|
||||
}
|
||||
case RxCMD:
|
||||
{
|
||||
Command = Data;
|
||||
mRxData[BufPtr++] = Data;
|
||||
State = RxSize1;
|
||||
CRC ^= Data;
|
||||
break;
|
||||
}
|
||||
case RxSize1: //Data size MSB
|
||||
{
|
||||
DataSize = 0;
|
||||
DataSize = (unsigned int)Data;
|
||||
DataSize <<= 8;
|
||||
mRxData[BufPtr++] = Data;
|
||||
|
||||
|
||||
State = RxSize2;
|
||||
CRC ^= Data;
|
||||
break;
|
||||
}
|
||||
case RxSize2: //Data size
|
||||
{
|
||||
DataSize |= (unsigned int)Data;
|
||||
DataSize <<= 8;
|
||||
mRxData[BufPtr++] = Data;
|
||||
|
||||
|
||||
State = RxSize3;
|
||||
CRC ^= Data;
|
||||
break;
|
||||
}
|
||||
case RxSize3: //Data size
|
||||
{
|
||||
DataSize |= (unsigned int)Data;
|
||||
DataSize <<= 8;
|
||||
mRxData[BufPtr++] = Data;
|
||||
|
||||
|
||||
State = RxSize4;
|
||||
CRC ^= Data;
|
||||
break;
|
||||
}
|
||||
|
||||
case RxSize4: //Data size LSB
|
||||
{
|
||||
DataSize |= (unsigned int)Data;
|
||||
mRxData[BufPtr++] = Data;
|
||||
|
||||
if(DataSize > MAX_MESSAGE_SIZE)
|
||||
ResetStateMachine();
|
||||
|
||||
if(DataSize == 0)
|
||||
State = RxCRC;
|
||||
else
|
||||
State = RxData;
|
||||
|
||||
CRC ^= Data;
|
||||
break;
|
||||
}
|
||||
case RxData:
|
||||
{
|
||||
CRC ^= Data;
|
||||
|
||||
mRxData[BufPtr++] = Data;
|
||||
DataCtr++;
|
||||
|
||||
if(DataCtr == DataSize)
|
||||
{
|
||||
State = RxCRC;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case RxCRC:
|
||||
{
|
||||
if(Data != CRC)
|
||||
{
|
||||
ResetStateMachine();
|
||||
// ProtocolAcknowledge(0,Command,0);
|
||||
break;
|
||||
}
|
||||
// NewMasterMessageReceived(mRxData);
|
||||
ExecuteMasterCommand(Command,ProtocolMsgDataPtr());
|
||||
ResetStateMachine();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ResetStateMachine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolAnalyzeNewData(unsigned char Data)
|
||||
{
|
||||
// mRxData[RxPtr] = Data;
|
||||
// printf("%X",Data);
|
||||
StateMachine(Data);
|
||||
}
|
||||
|
||||
void ResetStateMachine(void)
|
||||
{
|
||||
DataSize = 0;
|
||||
BufPtr = 0;
|
||||
RxPtr = 0;
|
||||
Command = 0;
|
||||
CRC = 0;
|
||||
State = RxHeader;
|
||||
DataCtr = 0;
|
||||
Flags = 0;
|
||||
SenderAddress = 0;
|
||||
}
|
||||
|
||||
void ProtocolExecCmd(void)
|
||||
{
|
||||
switch(Command)
|
||||
{
|
||||
case RX_GET_STATUS:
|
||||
{
|
||||
unsigned char StatusByte =0;
|
||||
// memcpy(&StatusByte, &IRRemoteStatus, sizeof(IRRemoteStatus));
|
||||
// ProtocolSendCmd(TX_DEADBOLT_STATUS,&StatusByte,sizeof(StatusByte),1,0);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProtocolAcknowledge(unsigned char Answer,unsigned char Cmd, unsigned char Data)
|
||||
{
|
||||
unsigned char data[2];
|
||||
if(Answer == 1)
|
||||
{
|
||||
data[0] = PROTOCOL_ACK; //CMD
|
||||
}
|
||||
else
|
||||
{
|
||||
data[0] = PROTOCOL_NAK; //CMD
|
||||
}
|
||||
data[1] = Cmd;
|
||||
|
||||
// ProtocolSendCmd(TX_NETWORK_ACK,&data[0],2,1,0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned char ProtocolCalcCrc(unsigned char* Buffer,unsigned char size)
|
||||
{
|
||||
unsigned char CRC = 0;
|
||||
unsigned char i;
|
||||
for(i = 0; i < size; i++)
|
||||
CRC ^= Buffer[i];
|
||||
|
||||
return CRC;
|
||||
}
|
||||
|
||||
unsigned char ProtocolIsReceiving(void)
|
||||
{
|
||||
if(State == RxHeader)
|
||||
return 0; // Idle...
|
||||
else
|
||||
return 1; //receiving from serial port
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned char* ProtocolGetFrame(unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags, int *FrameSize)
|
||||
{
|
||||
if(Size > MAX_MESSAGE_SIZE)
|
||||
{
|
||||
*FrameSize = 0;
|
||||
return &mTxData[FRAME_HEADER_INDEX];
|
||||
}
|
||||
|
||||
mTxData[FRAME_HEADER_INDEX] = FRAME_HEADER; //header
|
||||
mTxData[FRAME_SENDER_ADDRESS_INDEX] = MY_DEVICE_ADDRESS; //My Address
|
||||
mTxData[FRAME_SENDER_DEVICE_ID_INDEX] = SenderDevice; //My ID
|
||||
mTxData[FRAME_DEST_DEVICE_ID_INDEX] = DestDevice; //Destination ID
|
||||
mTxData[FRAME_DEST_ADDRESS_INDEX] = DestAddress ;//Address; //Destination Address
|
||||
mTxData[FRAME_FLAGS_INDEX] = Flags; //Flags
|
||||
mTxData[FRAME_COMMAND_INDEX] = Cmd; //Command to send
|
||||
mTxData[FRAME_SIZE1_INDEX] = (unsigned char)((Size >> 24) & 0xFF);
|
||||
mTxData[FRAME_SIZE2_INDEX] = (unsigned char)((Size >> 16) & 0xFF);
|
||||
mTxData[FRAME_SIZE3_INDEX] = (unsigned char)((Size >> 8) & 0xFF);
|
||||
mTxData[FRAME_SIZE4_INDEX] = (unsigned char)(Size & 0xFF);
|
||||
memcpy((void*)&mTxData[FRAME_DATA_INDEX],(void*)Data,Size); //Cmd data
|
||||
mTxData[Size+FRAME_DATA_INDEX] = ProtocolCalcCrc(mTxData,Size + FRAME_DATA_INDEX); // CRC
|
||||
|
||||
*FrameSize = Size + FRAME_INDEX_NBR;
|
||||
|
||||
return &mTxData[FRAME_HEADER_INDEX];
|
||||
|
||||
}
|
||||
|
||||
unsigned char *ProtocolMsgDataPtr()
|
||||
{
|
||||
return &mRxData[FRAME_DATA_INDEX];
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**********************************************************************
|
||||
Project: Automatic cat feeder
|
||||
Date: march 19 2006
|
||||
Author: Jean-Fran�ois Martel
|
||||
Target: PIC 18F252
|
||||
Compiler: Microchip mcc18
|
||||
Filename: Protocol.h
|
||||
|
||||
File description: Communication protocol implementation.
|
||||
|
||||
|
||||
jean-francois.martel@polymtl.ca
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
#ifndef BOOTLOADERINTERFACE_H
|
||||
#define BOOTLOADERINTERFACE_H
|
||||
|
||||
//Protocol buffer specific definitions
|
||||
|
||||
#define MASTER_ADDRESS 0x01
|
||||
#define MY_DEVICE_ADDRESS 0x01
|
||||
|
||||
#define ADDRESS 0x01
|
||||
|
||||
//State Machine states
|
||||
enum States
|
||||
{
|
||||
Initialization,
|
||||
RxHeader,
|
||||
RxAdd,
|
||||
RxID,
|
||||
RxMyID,
|
||||
RxMyAddress,
|
||||
RxFlags,
|
||||
RxCMD,
|
||||
RxSize1,
|
||||
RxSize2,
|
||||
RxSize3,
|
||||
RxSize4,
|
||||
RxData,
|
||||
RxCRC
|
||||
};
|
||||
|
||||
//enum DEVICES_IDS
|
||||
//{
|
||||
// ID_MASTER, //Master Controller
|
||||
// ID_CONSOLE, //LCD Console
|
||||
// ID_PC, //PC
|
||||
// ID_AV_MUX, //Audio Video Multiplexer
|
||||
// ID_IR_REMOTE,
|
||||
// ID_DEADBOLT
|
||||
//};
|
||||
|
||||
//enum MESSAGE_IDS
|
||||
//{
|
||||
// TX_NETWORK_ACK = 1,
|
||||
// RX_GET_STATUS,
|
||||
// TX_DEADBOLT_STATUS,
|
||||
//
|
||||
// MAX_NETWORK_CMD
|
||||
//};
|
||||
|
||||
//State machine states definition
|
||||
|
||||
void ProtocolInit(void);
|
||||
void StateMachine(unsigned char STATE);
|
||||
void ProtocolAnalyzeNewData(unsigned char RxByte);
|
||||
void ResetStateMachine(void);
|
||||
void ProtocolExecCmd(void);
|
||||
void ProtocolAcknowledge(unsigned char Answer,unsigned char Cmd, unsigned char Data);
|
||||
unsigned char* ProtocolGetFrame(unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags, int *FrameSize);
|
||||
unsigned char ProtocolCalcCrc(unsigned char* Buffer,unsigned char size);
|
||||
unsigned char ProtocolIsReceiving(void);
|
||||
unsigned char *ProtocolMsgDataPtr();
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "define.h"
|
||||
#include "Schedule.h"
|
||||
|
||||
void InitSchedule()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
|
||||
#ifndef TCPSERVER_H
|
||||
#define TCPSERVER_H
|
||||
|
||||
|
||||
int OpenTCPServer();
|
||||
void TickTCPServer();
|
||||
|
||||
|
||||
#endif
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 *)¶m, 0, sizeof(tstrWifiInitParam));
|
||||
/* Initialize Wi-Fi driver with data and status callbacks. */
|
||||
param.pfAppWifiCb = (void*) &wifi_cb;
|
||||
ret = m2m_wifi_init(¶m);
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* File: WiFiCtrl.h
|
||||
* Author: JF
|
||||
*
|
||||
* Created on December 8, 2018, 6:52 AM
|
||||
*/
|
||||
|
||||
#ifndef WIFICTRL_H
|
||||
#define WIFICTRL_H
|
||||
|
||||
#include "driver/include/m2m_wifi.h"
|
||||
#include "socket/include/socket.h"
|
||||
|
||||
/*!
|
||||
* Used for code portability.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @typedef void (*tpfNmBspIsr) (void);
|
||||
* @brief Pointer to function.\n
|
||||
* Used as a data type of ISR function registered by \ref nm_bsp_register_isr
|
||||
* @return None
|
||||
*/
|
||||
typedef void (*tpfNmBspIsr)(void);
|
||||
|
||||
/*!
|
||||
* @ingroup DataTypes
|
||||
* @typedef unsigned char uint8;
|
||||
* @brief Range of values between 0 to 255
|
||||
*/
|
||||
typedef unsigned char uint8;
|
||||
|
||||
/*!
|
||||
* @ingroup DataTypes
|
||||
* @typedef unsigned short uint16;
|
||||
* @brief Range of values between 0 to 65535
|
||||
*/
|
||||
typedef unsigned short uint16;
|
||||
|
||||
/*!
|
||||
* @ingroup Data Types
|
||||
* @typedef unsigned long uint32;
|
||||
* @brief Range of values between 0 to 4294967295
|
||||
*/
|
||||
typedef unsigned long uint32;
|
||||
|
||||
|
||||
/*!
|
||||
* @ingroup Data Types
|
||||
* @typedef signed char sint8;
|
||||
* @brief Range of values between -128 to 127
|
||||
*/
|
||||
typedef signed char sint8;
|
||||
|
||||
/*!
|
||||
* @ingroup DataTypes
|
||||
* @typedef signed short sint16;
|
||||
* @brief Range of values between -32768 to 32767
|
||||
*/
|
||||
typedef signed short sint16;
|
||||
|
||||
/*!
|
||||
* @ingroup DataTypes
|
||||
* @typedef signed long sint32;
|
||||
* @brief Range of values between -2147483648 to 2147483647
|
||||
*/
|
||||
|
||||
typedef signed long sint32;
|
||||
//@}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int InitWiFi();
|
||||
void TickWiFi();
|
||||
int TurnOFFWiFi();
|
||||
int CloseSockets();
|
||||
char GetWiFiSate();
|
||||
|
||||
int OpenTerminalServer();
|
||||
void SendTerminalData(uint8 *data, int size);
|
||||
void SentTerminalByte(uint8 data);
|
||||
|
||||
int OpenNetworkServer();
|
||||
void SendNetworkData(uint8 *data, int size);
|
||||
void SentNetworkByte(uint8 data);
|
||||
|
||||
int OpenSyslogServer();
|
||||
void SendSyslogData(uint8 *data, int size);
|
||||
void SendSyslogByte(uint8 data);
|
||||
int IsSyslogClientConnected();
|
||||
|
||||
int OpenBootloaderServer();
|
||||
int CloseBootloaderServer();
|
||||
void SendBootloaderData(uint8 *data, int size);
|
||||
void SendBootloaderByte(uint8 data);
|
||||
int IsBootloaderClientConnected();
|
||||
|
||||
//#define USE_STATIC_IP
|
||||
|
||||
|
||||
// <<< Use Configuration Wizard in Context Menu >>>
|
||||
//<h> General network settings in AP (access point) mode
|
||||
// <s> Network SSID
|
||||
// <id> app_main_m2m_device_name
|
||||
#ifndef MAIN_M2M_SSID
|
||||
#define MAIN_M2M_SSID "WINC3400_00:00"
|
||||
#endif
|
||||
|
||||
// <o> Security type
|
||||
// <1=> Wi-Fi network is not secured
|
||||
// <2=> WPA/WPA2 personal(PSK)
|
||||
// <3=> WEP (40 or 104) OPEN OR SHARED
|
||||
// <4=> WPA/WPA2 Enterprise.IEEE802.1x
|
||||
// <id> app_main_m2m_ap_sec
|
||||
#ifndef MAIN_M2M_AP_SEC
|
||||
#define MAIN_M2M_AP_SEC 1
|
||||
#endif
|
||||
|
||||
// <s> Security key
|
||||
// <id> app_main_m2m_ap_key
|
||||
#ifndef MAIN_M2M_AP_KEY
|
||||
#define MAIN_M2M_AP_KEY "12345FFFFF"
|
||||
#endif
|
||||
|
||||
// <o> SSID mode
|
||||
// <0=>SSID is visible to others
|
||||
// <1=>SSID is hidden
|
||||
// <id> app_main_m2m_ap_ssid_mode
|
||||
#ifndef MAIN_M2M_AP_SSID_MODE
|
||||
#define MAIN_M2M_AP_SSID_MODE 0
|
||||
#endif
|
||||
//</h>
|
||||
//<h> DHCP server IP address in AP (access point) mode
|
||||
// <o> DHCP serv
|
||||
Reference in New Issue
Block a user