#include // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules
#include "PSoCGPIOInt.h"
//-------------------------------------------------------------------------
//
//#defines
//
//-------------------------------------------------------------------------
// Maximum Buffer length
#define MAX_BUFF_PKTS 12 // Reduce for HiTech PRO
#define MAX_PAYLOAD 14
#define I2C_PKT_SIZE 0x12
//Backchannel masks
#define DEV_ID_MSK 0x1F
//Host Command Definitions
#define HOST_CONFIG_STATUS 0x01
#define FETCH_NXT_PKT 0x02
#define SEND_PKT 0x03
#define GET_NODE_CFG 0x04
#define UNBIND_NODE 0x05
#define ENTER_BIND_MODE 0x06
#define GET_LAST_BIND_RESULT 0x07
//Hub Response Definitions
#define HOST_CONFIG_STATUS_RSP 0x81
#define FETCH_NXT_PKT_RSP 0x82
#define SEND_PKT_RSP 0x83
#define GET_NODE_CFG_RSP 0x84
#define UNBIND_NODE_RSP 0x85
#define ENTER_BIND_MODE_RSP 0x86
#define GET_LAST_BIND_RESULT_RSP 0x87
#define NETWORK_SIZE 0x1F
//Host Command Masks
#define OPTION_LEN_MSK 0xF0
#define OPTION_FLUSH_MSK 0x10
//Hub Response masks
#define NODE_STATUS_MSK 0x03
//Status
#define STATUS_SUCCESS 0x01
#define STATUS_FAILURE 0x00
#define MAX_PAYLOAD_BCD 0x06
//Host command byte Defines
#define COMMAND_BYTE 0x00
//Hub response byte defines
#define RESPONSE_BYTE 0x00
#define IN_BIND_MODE 0x02
#define NOT_IN_BIND_MODE 0x01
#define BIND_TIMEOUT 0x00
//Device Types
#define FIRST_TOUCH_RF_DEVICE 0x00
//FW Version
#define FW_VERSION 0x01
//Misc
#define RESERVED 0x00
//-------------------------------------------------------------------------
//
//Function Prototypes
//
//-------------------------------------------------------------------------
void ServeSNPPackets(void);
void CheckHostRequest(void);
void BufferManagement(void);
void SendBackChannelData(BYTE devId);
void WriteBufferManager(void);
void ReadBufferManager(void);
static BOOL bindButtonIsOn(void);
static BOOL checkBindButton(void);
//-------------------------------------------------------------------------
//
//Global Variables and Structures
//
//-------------------------------------------------------------------------
typedef struct
{
BYTE length; // Payload length
BYTE rssi; // RSSI of packet
BYTE type; // Packet type
BYTE devId; // [7:0] = Device ID
BYTE payload[CYFISNP_FCD_PAYLOAD_MAX]; //
} APP_PKT;
//Packet Buffer
APP_PKT App_Buff[MAX_BUFF_PKTS];
//Application Variables
char payload_data[16];
BYTE devId = 0;
char length = 0;
char packet_type = 0;
unsigned int numberOfPacketsInBuffer = 0;
char fiveBitDeviceId = 0;
//I2C variables
//unsigned char Read_buff[20];//Buffer in I2C Slave from which Master reads
unsigned char I2CBuffer[20];//Buffer to receive Host command from master
//Pointer to first packet in Read buffer
char *pI2C = &I2CBuffer[0];//Pointer to first packet in Command Buffer
//Host Command 0x02 variables
BYTE options = 0;
BYTE lengthOfHostMessage = 0;
BOOL flush = FALSE;
BYTE status = STATUS_SUCCESS;
BYTE count = 0;
//Host Command 0x03 variables
BYTE nodeStatus = 0x00;
BYTE threeBitNodeStatus = 0x00;
//Buffer Management Flags
BOOL bAppBuffFull = FALSE;
BOOL bAppBuffEmpty = TRUE;
BOOL bAppBuffNotFull = TRUE;
//I2C Flags
BOOL bHostDataRequest = FALSE;
//Bind Variables
BYTE boundNodeId = 0;
BYTE boundNodeMID[4];
BOOL bBindTimeOut = FALSE;
//CYFISNP Pointers
CYFISNP_API_PKT *pApiPkt;
CYFISNP_API_PKT sTestTxPkt; //instantiation of CYFISNP_API_PKT
//MID Buffer
BYTE MID_buff[6];
//Buffer Management Pointers
APP_PKT *pNextWrite = &App_Buff[0]; //Pointer to next write packet location in Buffer
APP_PKT *pNextRead = &App_Buff[0]; //Pointer to next read packet location in Buffer
APP_PKT *pEnd = &App_Buff[MAX_BUFF_PKTS]; //Pointer to end address of Buffer
APP_PKT *pBeg = &App_Buff[0];
#include "CYFISNP_protocol.h"
#define ENABLE_BIND_BUTTON 0
static void showSignon (void);
static void showDevRecords (void);
static void showLeds (void);
// ---------------------------------------------------------------------------
// Private variables
// ---------------------------------------------------------------------------
static BOOL redLedTimerOn;
static WORD redLedTimer;
#define RED_LED_TIME_BINDOK 1000/CYFISNP_TIMER_UNITS // Bind Rsp LED Pulse time
#define RED_LED_TIME_BINDTOG 250/CYFISNP_TIMER_UNITS // Bind Mode blink
static BOOL grnLedTimerOn;
static WORD grnLedTimer;
#define GRN_LED_TIME_RXPKT 50/CYFISNP_TIMER_UNITS // Rx packet flicker
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
//
// main()
//
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
void main()
{
BYTE i = 0;
EzI2Cs_SetRamBuffer(sizeof(I2CBuffer), sizeof(I2CBuffer), pI2C); //set up RAM buffer
M8C_EnableGInt; //Enable Interrupts
EzI2Cs_Start(); //Turn on I2C
LED_GREEN_Start(); //Turn on LED
LED_RED_Start();
LED_GREEN_On();
#if CYFISNP_DEBUG || DEBUG_I2C
TX8_Start(0);
showDevRecords();
showSignon();
#endif
LED_GREEN_Off();
CYFISNP_Start();// Start Protocol (and radio)
// -----------------------------------------------------------------------
// POLLING LOOP
// -----------------------------------------------------------------------
while (1) {
CYFISNP_Run(); // Run CYFISNP once thru the loop.
//check for bind button press and if pressed call CYFISNP_BindStart
#if ENABLE_BIND_BUTTON
if (checkBindButton()) {
boundNodeId = 0; // Clear prior bind result
CYFISNP_BindStart();
}
#endif
showLeds();
if (CYFISNP_RxDataPend()) { // If SNP Rx data pending
CYFISNP_TimeSet(&grnLedTimer, GRN_LED_TIME_RXPKT);
grnLedTimerOn = TRUE;
LED_GREEN_On();
ServeSNPPackets(); // the service it
}
CheckHostRequest(); //check if Host has a pending request
}
}//end of main program
///---------------------------------------------------------------------------
// ServeSNPPackets() - A SNP Rx packet is pending, copy the packet to I2C buffer
// and store in the buffer.
//
//Variables:
// pApiPkt - pointer to SNP data
// numberOfPacketsInBuffer - running packet count in the hub buffer
// pNextWrite - pointer to the start of where the data is going to
// be placed that was received from SNP
//----------------------------------------------------------------------------
void ServeSNPPackets(void)
{
BYTE index = 0;
if (numberOfPacketsInBuffer != MAX_BUFF_PKTS) {
pApiPkt = CYFISNP_RxDataGet(); // ptr to Rx API Packet
devId = pApiPkt->devId;
switch (pApiPkt->type) {
//--------------------------------------------------------------------
case CYFISNP_API_TYPE_BIND_RSP_ACK:
boundNodeId = pApiPkt->devId;
boundNodeMID[0] = pApiPkt->payload[0];
boundNodeMID[1] = pApiPkt->payload[1];
boundNodeMID[2] = pApiPkt->payload[2];
boundNodeMID[3] = pApiPkt->payload[3];
CYFISNP_TimeSet(&redLedTimer, RED_LED_TIME_BINDOK);
redLedTimerOn = TRUE;
#ifdef CYFISNP_DEBUG
CYFISNP_OutStr("\n\rSNP_BRespAck MID=");
CYFISNP_OutHex(boundNodeMID[0]); CYFISNP_OutHex(boundNodeMID[1]);
CYFISNP_OutHex(boundNodeMID[2]); CYFISNP_OutHex(boundNodeMID[3]);
#endif
break;
//--------------------------------------------------------------------
case CYFISNP_API_TYPE_CONF_BCDR:
case CYFISNP_API_TYPE_CONF:
case CYFISNP_API_TYPE_SYNC_BCDR:
case CYFISNP_API_TYPE_SYNC:
pNextWrite->length = pApiPkt->length;
pNextWrite->rssi = pApiPkt->rssi;
pNextWrite->devId = pApiPkt->devId;
length = pApiPkt->length;
for (index = 0; index<=length; index++) {
pNextWrite->payload[index] = pApiPkt->payload[index];
}
WriteBufferManager(); // manage pointer and buffer
#if CYFISNP_DEBUG
CYFISNP_OutStr("Packets=");
CYFISNP_OutHex(numberOfPacketsInBuffer);
#endif
break;
default:
break;
}
CYFISNP_RxDataRelease(); // Release pApiPkt pointer back to SNP so we can get the next SNP packet
}
}
#if ENABLE_BIND_BUTTON
//----------------------------------------------------------------------------
//
// checkBindButton() Check if bind button is pushed. If it is return true.
//
//----------------------------------------------------------------------------
#define DEBOUNCE_TIME 2
static BOOL bindButtonIsOn(void)
{
BIND_BUTTON_Data_ADDR &= ~BIND_BUTTON_MASK; // Ensure GPIO pulldown active
return((BIND_BUTTON_Data_ADDR & BIND_BUTTON_MASK) != 0);
}
static BOOL checkBindButton(void)
{
WORD lvDelay;
if (bindButtonIsOn()) {
CYFISNP_TimeSet(&lvDelay, DEBOUNCE_TIME); // Debouncing, delay 20ms
while (CYFISNP_TimeExpired(&lvDelay) == 0) ; // WAIT
if (bindButtonIsOn()) { // If button still ON
while (bindButtonIsOn()) {
M8C_ClearWDTAndSleep; // Wait for button release
}
return TRUE;
}
}
return FALSE;
}
#endif
//----------------------------------------------------------------------------
//
// CheckHostRequest() - Of the host has made a request for a packet, figure out
// what type of packet is requested and return it thru the
// I2C Buffer
//
//Variables:
// I2CBuffer - buffer that EZI2C has access to. Used when hub wants to
// return data back to host.
// sTestTxPkt - instantiation of CYFISNP_API_PKT. Used so data can be
// put in the defined structure by SNP
// numberOfPacketsInBuffer - running packet count in the hub buffer
// pNextRead - pointer to the start of the next set of data to return
// to host.
//----------------------------------------------------------------------------
void CheckHostRequest()
{
BYTE i = 0;
BYTE index = 0;
BYTE payloadIndex = 0;
switch (I2CBuffer[COMMAND_BYTE]) {
case HOST_CONFIG_STATUS:
#ifdef DEBUG_I2C
CYFISNP_OutStr("\n\rI2C_Cfg_Stat");
#endif
I2CBuffer[1] = FIRST_TOUCH_RF_DEVICE;
I2CBuffer[2] = FW_VERSION;
// I2CBuffer[3] = (BYTE)CYFISNP_eProtState; //current state of SNP Protocol
CYFISNP_SetPtr(&I2CBuffer[4]);
CYFISNP_SetLength(0x04);
CYFISNP_GetFuses();
I2CBuffer[8] = RESERVED;
I2CBuffer[9] = NETWORK_SIZE;
I2CBuffer[0] = HOST_CONFIG_STATUS_RSP;
break;
// -----------------------------------------------------------------------
// get next packet from hub buffer and return to HOST via I2CBuffer
// -----------------------------------------------------------------------
case FETCH_NXT_PKT:
#ifdef DEBUG_I2C
CYFISNP_OutStr("*");
#endif
if (numberOfPacketsInBuffer != 0) {
#ifdef DEBUG_I2C
CYFISNP_OutStr("\n\rI2C_Fetch");
#endif
length = pNextRead->length;
devId = pNextRead->devId;
//stuff I2C buffer with data
I2CBuffer[1] = numberOfPacketsInBuffer;
I2CBuffer[2] = length;
I2CBuffer[3] = pNextRead->rssi;
I2CBuffer[4] = RESERVED;
I2CBuffer[5] = devId;
for (index=6; index < (length+6); index++) {
I2CBuffer[index] = pNextRead->payload[payloadIndex];
payloadIndex++;
}
ReadBufferManager();
} else {
I2CBuffer[1] = 0xFF; // if no more messages are in the buffer return 0xFF
}
I2CBuffer[RESPONSE_BYTE] = FETCH_NXT_PKT_RSP;
break;
// -----------------------------------------------------------------------
// Host wants to send back channel data to node. Grab the data and format it to SNP structure and send it to node.
// -----------------------------------------------------------------------
case SEND_PKT:
#ifdef DEBUG_I2C
CYFISNP_OutStr("\n\rI2C_SendPkt");
#endif
status = STATUS_SUCCESS;
lengthOfHostMessage = I2CBuffer[2] & OPTION_LEN_MSK;
flush = I2CBuffer[2] & OPTION_FLUSH_MSK;
for (i =0; i <= lengthOfHostMessage; i++) {
sTestTxPkt.payload[i] = I2CBuffer[i+3];
}
sTestTxPkt.length = lengthOfHostMessage;
sTestTxPkt.type = CYFISNP_API_TYPE_CONF_BCDR;
sTestTxPkt.devId = I2CBuffer[1];
if (lengthOfHostMessage < MAX_PAYLOAD_BCD) {
if (flush) {
if (CYFISNP_TxDataPut(&sTestTxPkt)) {
status = STATUS_SUCCESS;
}
}
}
I2CBuffer[1] = status;
I2CBuffer[RESPONSE_BYTE] = SEND_PKT_RSP;
break;
// -----------------------------------------------------------------------
//ask SNP to return a specific Node's MID. if the device ID requested by the HOST is 0x00 then return the MID of the hub.
// -----------------------------------------------------------------------
case GET_NODE_CFG:
devId = I2CBuffer[1]; // Get the device ID from the I2C command
#ifdef DEBUG_I2C
CYFISNP_OutStr("\n\rI2C_GetNodeCFG ID=");
CYFISNP_OutHex(devId);
#endif
if (CYFISNP_LookupMid(&I2CBuffer[2], devId)) { // devId & 0x1f because SNP needs only the node id not node id and pin.
I2CBuffer[1] = STATUS_SUCCESS;
I2CBuffer[6] = CYFISNP_TxDataPend(devId);
#ifdef DEBUG_I2C
CYFISNP_OutStr(" MID=");
CYFISNP_OutHex(I2CBuffer[2]); CYFISNP_OutHex(I2CBuffer[3]);
CYFISNP_OutHex(I2CBuffer[4]); CYFISNP_OutHex(I2CBuffer[5]);
#endif
} else {
I2CBuffer[1] = STATUS_FAILURE;
}
I2CBuffer[RESPONSE_BYTE] = GET_NODE_CFG_RSP;
break;
// -----------------------------------------------------------------------
// Unbind specific device.
// -----------------------------------------------------------------------
case UNBIND_NODE:
#ifdef DEBUG_I2C
CYFISNP_OutStr("\n\rI2C_Unbind");
#endif
devId = I2CBuffer[1];
if (devId == 0xFF) {
for (i=1; i<=NETWORK_SIZE; i++)
CYFISNP_UnbindDevId(i);
I2CBuffer[1] = STATUS_SUCCESS;
} else {
I2CBuffer[1] = CYFISNP_UnbindDevId(devId);
}
I2CBuffer[RESPONSE_BYTE] = UNBIND_NODE_RSP;
break;
// -----------------------------------------------------------------------
// Enter Bind Mode
// -----------------------------------------------------------------------
case ENTER_BIND_MODE:
#ifdef DEBUG_I2C
CYFISNP_OutStr("\n\rI2C_Ent_B");
#endif
boundNodeId = 0; // Clear prior bind result
CYFISNP_BindStart();
bBindTimeOut = TRUE; //set bind timeout as default state
I2CBuffer[1] = STATUS_SUCCESS;
I2CBuffer[RESPONSE_BYTE] = ENTER_BIND_MODE_RSP;
break;
// -----------------------------------------------------------------------
// Report Bind State {active, bound, timeout}
// -----------------------------------------------------------------------
case GET_LAST_BIND_RESULT:
if (CYFISNP_eProtState == CYFISNP_BIND_MODE) {
I2CBuffer[1] = IN_BIND_MODE;
}
else if (boundNodeId != 0) {
I2CBuffer[1] = NOT_IN_BIND_MODE;
I2CBuffer[2] = boundNodeId;
}
else {
I2CBuffer[1] = BIND_TIMEOUT;
}
I2CBuffer[RESPONSE_BYTE] = GET_LAST_BIND_RESULT_RSP;
break;
// -----------------------------------------------------------------------
default:
break;
}
}
//----------------------------------------------------------------------------
//
// SendBackChannelData() = Copnstruct back channel data to send to node.
//
//Variables:
// sTestTxPkt - instantiation of CYFISNP_API_PKT. Used so data can be
// put in the defined structure by SNP
//
//----------------------------------------------------------------------------
void SendBackChannelData(BYTE devId)
{
sTestTxPkt.length = CYFISNP_BCD_PAYLOAD_MAX;
sTestTxPkt.type = CYFISNP_API_TYPE_CONF;
sTestTxPkt.devId = devId;
sTestTxPkt.payload[1] = 0x2A;
sTestTxPkt.payload[2] = 0x0E;
sTestTxPkt.payload[3] = 0x4C;
sTestTxPkt.payload[4] = 0x8F;
sTestTxPkt.payload[5] = 0x7D;
//Hand off to protocol
}
void WriteBufferManager()
{
numberOfPacketsInBuffer++; // increment packet count
BufferManagement(); // call buffer management to check for full or empty condition
pNextWrite++; // increment next write pointer
}
void ReadBufferManager()
{
numberOfPacketsInBuffer--;
pNextRead++; // update read pointer, and call application memory management
BufferManagement();
}
//-------------------------------------------------------------------------------
//
// BufferManagement() - Manage pointers to make sure they wrap around.
//
//--------------------------------------------------------------------------------
void BufferManagement()
{
if (pNextRead == pEnd) {
pNextRead = pBeg;
}
if (numberOfPacketsInBuffer == 0) {
pNextWrite = &App_Buff[0];
pNextRead = &App_Buff[0];
}
if (numberOfPacketsInBuffer == MAX_BUFF_PKTS) {
CYFISNP_OutStr("\n\r");
}
if ((pNextWrite == pEnd) && (numberOfPacketsInBuffer != MAX_BUFF_PKTS )) {
pNextWrite = pBeg; //Reset to beggining of Buffer
}
if (pNextRead == pEnd) {
pNextRead = pBeg; //Reset to beggining of buffer
}
}
// ---------------------------------------------------------------------------
//
// showLeds() - Run the RED LED showDevRecords
//
// ---------------------------------------------------------------------------
static void showLeds(void)
{
#ifdef CYFISNP_DEBUG
static CYFISNP_PROT_STATE eProtStateOld;
if (eProtStateOld != CYFISNP_eProtState) {
eProtStateOld = CYFISNP_eProtState;
switch (CYFISNP_eProtState) {
case CYFISNP_BIND_MODE: CYFISNP_OutStr(""); break;
case CYFISNP_DATA_MODE: CYFISNP_OutStr(""); break;
case CYFISNP_PING_MODE: CYFISNP_OutStr("
"); break;
default: CYFISNP_OutStr("??_MODE>");
}
}
#endif
if (CYFISNP_eProtState == CYFISNP_BIND_MODE) {
if (redLedTimer == FALSE) {
redLedTimer = TRUE;
LED_RED_On();
CYFISNP_TimeSet(&redLedTimer, RED_LED_TIME_BINDTOG);
}
else if (CYFISNP_TimeExpired(&redLedTimer)) {
CYFISNP_TimeSet(&redLedTimer, RED_LED_TIME_BINDTOG);
LED_RED_Invert();
}
}
else if (redLedTimerOn == TRUE) { // Not in Bind Mode
if (CYFISNP_TimeExpired(&redLedTimer)) {
LED_RED_Off();
redLedTimerOn = FALSE;
}
} else {
LED_RED_Off();
}
if (grnLedTimerOn) {
if (CYFISNP_TimeExpired(&grnLedTimer)) {
LED_GREEN_Off();
}
}
}
#ifdef CYFISNP_DEBUG
// ---------------------------------------------------------------------------
// showSignon()
// ---------------------------------------------------------------------------
static void showSignon(void) {
CYFISNP_OutStr("\r\n\n\n");
CYFISNP_OutStr(__FILE__);
#if HI_TECH_C
CYFISNP_OutStr(" by HiTech "); CYFISNP_OutHex(_HTC_VER_MAJOR_);
CYFISNP_OutStr("."); CYFISNP_OutHex(_HTC_VER_MINOR_);
CYFISNP_OutStr("."); CYFISNP_OutHex(_HTC_VER_PATCH_);
#else
CYFISNP_OutStr(" by ImageCraft");
#endif
CYFISNP_OutStr(" on ");
CYFISNP_OutStr(__DATE__); CYFISNP_OutStr(", ");
CYFISNP_OutStr(__TIME__);
// ---------------------------------------------------------------------------
CYFISNP_OutStr(" ExtPA=");
#if CYFISNP_EXTERNAL_PA
CYFISNP_OutStr("Yes\n\r");
#else
CYFISNP_OutStr("No\n\r");
#endif
// ---------------------------------------------------------------------------
}
// ---------------------------------------------------------------------------
// showDevRecords() Display device and mid table
// ---------------------------------------------------------------------------
static void showDevRecords(void) {
char ivar;
char jvar;
char devId;
CYFISNP_OutStr("\n\rDEV PinDev FLG MID");
for (ivar=1; ivar <= CYFISNP_MAX_NODES; ++ivar) {
devId = (CYFISNP_EEP_DEV_REC_ADR+ivar)->devId;
if (devId != 0) {
CYFISNP_OutStr("\n\r");
CYFISNP_OutHex(devId); CYFISNP_OutStr(", ");
CYFISNP_OutHex((CYFISNP_EEP_DEV_REC_ADR+devId)->devId); CYFISNP_OutStr(", ");
CYFISNP_OutHex((CYFISNP_EEP_DEV_REC_ADR+devId)->flg); CYFISNP_OutStr(" ");
for (jvar=0; jvar < CYFISNP_SIZEOF_MID; ++jvar) {
CYFISNP_OutChar(' ');
CYFISNP_OutHex((CYFISNP_EEP_DEV_REC_ADR+devId)->devMid[jvar]);
}
if (ivar != devId) {
CYFISNP_OutStr(" <-- ??? Device ID wrong");
}
}
}
CYFISNP_OutStr("\n\r");
}
#endif
// ###########################################################################
Dostları ilə paylaş: |