502 lines
11 KiB
C
502 lines
11 KiB
C
/*
|
|
rf.c -
|
|
Copyright (C) 2008
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "lpc2220.h"
|
|
#include "rf.h"
|
|
#include "cc1100.h"
|
|
#include "timerfuncs.h"
|
|
#include "irq.h"
|
|
#include "cc1100.h"
|
|
#include "lcd.h"
|
|
#include "fonty.h"
|
|
#include "rtc.h"
|
|
#include "global.h"
|
|
#include "buffer.h"
|
|
#include "bfs.h"
|
|
|
|
unsigned char RFbuf[64];
|
|
struct RFendpoint_ rfendpoint[MAX_ENDPOINTS];
|
|
struct RF_ RF;
|
|
|
|
const struct RFsettings_ default_RFsettings =
|
|
{
|
|
0x01, //address
|
|
0x01 //channel
|
|
};
|
|
|
|
//*********************
|
|
//* Private functions *
|
|
//*********************
|
|
|
|
void switch_to_idle() {
|
|
cc1100_strobe(SIDLE);
|
|
while (cc1100_read1(MARCSTATE) != 01);
|
|
}
|
|
|
|
void WORsend_timeout(unsigned int cb) {
|
|
RF.state = RFsendworend;
|
|
}
|
|
|
|
void RF_timed_rx_timeout(unsigned int cb) {
|
|
stopCB(RF.timeout_cb);
|
|
removeTimerCB(RF.timeout_cb);
|
|
RF.timeout_cb = 0xff;
|
|
if(RF.flags & WORenabled)
|
|
RF_changestate(RFwor);
|
|
else
|
|
RF_changestate(RFidle);
|
|
|
|
}
|
|
|
|
void sendendpoint(struct RFendpoint_ *currentEP) {
|
|
|
|
unsigned char* epdata = 0;
|
|
unsigned short eplen;
|
|
struct cc1100frame_ *TXframe;
|
|
|
|
TXframe = (struct cc1100frame_ *)RFbuf;
|
|
|
|
//write header
|
|
eplen = currentEP->bufferlen;
|
|
switch ( currentEP->flags & EPtypemask) {
|
|
case EPtypedata:
|
|
if(eplen > 6)
|
|
eplen = 6;
|
|
epdata = currentEP->data;
|
|
break;
|
|
case EPtypebuffer:
|
|
if(eplen > 59)
|
|
eplen = 59;
|
|
epdata = currentEP->buffer;
|
|
break;
|
|
case EPtypecbuffer:
|
|
if(eplen > 59)
|
|
eplen = 59;
|
|
if(eplen > currentEP->cbuffer->len)
|
|
eplen = currentEP->cbuffer->len;
|
|
break;
|
|
}
|
|
TXframe->len = eplen + 3;
|
|
TXframe->destAddr = currentEP->dest;
|
|
TXframe->srcAddr = RF.addr;
|
|
TXframe->packetType = currentEP->type;
|
|
cc1100_write(TX_fifo | BURST,(unsigned char*)TXframe,4);
|
|
|
|
//write data
|
|
switch ( currentEP->flags & EPtypemask) {
|
|
case EPtypedata:
|
|
case EPtypebuffer:
|
|
cc1100_write(TX_fifo | BURST,epdata,eplen);
|
|
break;
|
|
case EPtypecbuffer:
|
|
|
|
if(currentEP->cbuffer->index + eplen <= currentEP->cbuffer->size) {
|
|
cc1100_write(TX_fifo | BURST,&(currentEP->cbuffer->data[currentEP->cbuffer->index]),eplen);
|
|
}
|
|
else {
|
|
cc1100_write(TX_fifo | BURST,&(currentEP->cbuffer->data[currentEP->cbuffer->index]), currentEP->cbuffer->size - currentEP->cbuffer->index);
|
|
cc1100_write(TX_fifo | BURST,currentEP->cbuffer->data,eplen - (currentEP->cbuffer->size - currentEP->cbuffer->index));
|
|
}
|
|
currentEP->cbuffer->index = (currentEP->cbuffer->index + eplen) % currentEP->cbuffer->size;
|
|
currentEP->cbuffer->len -= eplen;
|
|
break;
|
|
}
|
|
|
|
cc1100_strobe(STX);
|
|
|
|
currentEP->flags &= ~EPnewdata;
|
|
|
|
if(currentEP->flags & EPonce)
|
|
closeEP(currentEP);
|
|
}
|
|
|
|
void receiveendpoint(struct RFendpoint_ *currentEP) {
|
|
|
|
unsigned short eplen;
|
|
struct cc1100frame_ *RXframe;
|
|
|
|
RXframe = (struct cc1100frame_ *)RFbuf;
|
|
|
|
currentEP->dest = RXframe->srcAddr;
|
|
eplen = RXframe->len-3;
|
|
|
|
switch ( currentEP->flags & EPtypemask) {
|
|
case EPtypedata:
|
|
if(eplen > 6) {
|
|
eplen = 6;
|
|
currentEP->flags |= EPoverflow;
|
|
}
|
|
memcpy(&(currentEP->data[0]),RXframe->data,eplen);
|
|
break;
|
|
case EPtypebuffer:
|
|
if(eplen > currentEP->buffersize) {
|
|
eplen = currentEP->buffersize;
|
|
currentEP->flags |= EPoverflow;
|
|
}
|
|
memcpy(currentEP->buffer,RXframe->data,eplen);
|
|
break;
|
|
case EPtypecbuffer:
|
|
if(eplen > currentEP->cbuffer->size - currentEP->cbuffer->len) {
|
|
eplen = currentEP->cbuffer->size - currentEP->cbuffer->len;
|
|
currentEP->flags |= EPoverflow;
|
|
}
|
|
cBufferAddBuffer(currentEP->cbuffer, RXframe->data, eplen);
|
|
break;
|
|
}
|
|
|
|
currentEP->bufferlen = eplen;
|
|
if(currentEP->flags & EPnewdata)
|
|
currentEP->flags |= EPoverwritten;
|
|
else
|
|
currentEP->flags |= EPnewdata;
|
|
if(currentEP->flags & EPonce)
|
|
closeEP(currentEP);
|
|
}
|
|
|
|
void cc1100IRQ (void) {
|
|
|
|
unsigned char x;
|
|
|
|
switch_to_idle();
|
|
|
|
if (cc1100_read1(RXBYTES) > 0) {
|
|
cc1100_read(RX_fifo, RFbuf,1);
|
|
cc1100_read(RX_fifo, &RFbuf[1],RFbuf[0]);
|
|
|
|
struct cc1100frame_ *RXframe;
|
|
RXframe = (struct cc1100frame_ *)RFbuf;
|
|
|
|
if ((RXframe->len == 1) && (RF.flags & WORenabled) && ((RXframe->destAddr == RF.addr) || (RXframe->destAddr == 0x00))) {
|
|
if(RF.timeout_cb != 0xff || RF.state != RFrx)
|
|
RF_timed_rx(WORrx_time);
|
|
}
|
|
|
|
if (RXframe->len > 3) {
|
|
if (RF.timeout_cb != 0xff)
|
|
setCBIntervall(RF.timeout_cb,WORrx_time);
|
|
switch ( RXframe->packetType) {
|
|
case packet_test:
|
|
draw_block(0,50,128,10,3,DRAW_ERASE);
|
|
draw_string(0, 50, (char*)&RXframe->data[0], 3, DRAW_PUT);
|
|
break;
|
|
case packet_ping:
|
|
if (RXframe->data[0] == 0x01) {
|
|
struct RFendpoint_* cur_ep;
|
|
cur_ep = openEP(0,0, packet_ping);
|
|
if(cur_ep) {
|
|
cur_ep->dest = RXframe->srcAddr;
|
|
cur_ep->data[0] = 2;
|
|
cur_ep->bufferlen = 1;
|
|
cur_ep->flags |= EPenabled | EPoutput | EPnewdata | EPonce;
|
|
RF_changestate(RFtx);
|
|
}
|
|
}
|
|
else if (RXframe->data[0] == 0x02) {
|
|
RF.flags |= PingACK;
|
|
}
|
|
break;
|
|
case packet_time:
|
|
if ((RXframe->data[0] == 0xFF) && (timeInfo & TIME_ACCURATE)) {
|
|
send_time(RXframe->srcAddr,0);
|
|
}
|
|
else if (RXframe->len == 10) {
|
|
memcpy((unsigned char *)&rtc,&RXframe->data[0],7);
|
|
timeInfo |= SETNEWTIME;
|
|
VICSoftInt = INT_EINT2;
|
|
}
|
|
break;
|
|
default:
|
|
for(x=0; x<MAX_ENDPOINTS; x++) {
|
|
if((rfendpoint[x].type == RXframe->packetType) && ((rfendpoint[x].flags & (EPoutput | EPenabled)) == EPenabled)) {
|
|
receiveendpoint(&rfendpoint[x]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(RF.state == RFtx) {
|
|
for(x=0; x<MAX_ENDPOINTS; x++) {
|
|
if((rfendpoint[x].type) && ((rfendpoint[x].flags & (EPoutput | EPnewdata | EPenabled)) == (EPoutput | EPnewdata | EPenabled))) {
|
|
if(rfendpoint[x].flags & EPsendwor) {
|
|
rfendpoint[x].flags &= ~EPsendwor;
|
|
cc1100_write1(MCSM0,conf[MCSM0] & 0xCF);
|
|
cc1100_strobe(SCAL);
|
|
while (cc1100_read1(MARCSTATE) != 01);
|
|
RF.wortimeout_cb = addTimerCB(WORsend_timeout, 101);
|
|
startCB(RF.wortimeout_cb);
|
|
RF.state = RFsendwor;
|
|
RF.tag = x;
|
|
}
|
|
else
|
|
sendendpoint(&rfendpoint[x]);
|
|
break;
|
|
}
|
|
}
|
|
if(x == MAX_ENDPOINTS) {
|
|
RF.state = RF.nextstate;
|
|
}
|
|
}
|
|
|
|
if(RF.state == RFsendwor) {
|
|
unsigned char b[2];
|
|
b[0]=0x01;
|
|
b[1]=rfendpoint[RF.tag].dest;
|
|
cc1100_write(TX_fifo | BURST,b,2);
|
|
cc1100_strobe(STX);
|
|
}
|
|
|
|
if(RF.state == RFsendworend) {
|
|
stopCB(RF.wortimeout_cb);
|
|
removeTimerCB(RF.wortimeout_cb);
|
|
RF.wortimeout_cb = 0xff;
|
|
|
|
cc1100_write1(MCSM0,conf[MCSM0]);
|
|
RF.state = RFtx;
|
|
sendendpoint(&rfendpoint[RF.tag]);
|
|
}
|
|
|
|
switch (RF.state) {
|
|
case RFpwrdown:
|
|
cc1100_strobe(SPWD);
|
|
break;
|
|
case RFwor:
|
|
if(!(RF.flags & RXueop)) {
|
|
cc1100_write1(0x16,conf[0x16]);
|
|
RF.flags |= RXueop;
|
|
}
|
|
cc1100_strobe(SWOR);
|
|
break;
|
|
case RFidle:
|
|
break;
|
|
case RFrx:
|
|
if(RF.flags & RXueop) {
|
|
cc1100_write1(0x16,0x07);
|
|
RF.flags &= ~RXueop;
|
|
}
|
|
cc1100_strobe(SFRX);
|
|
cc1100_strobe(SRX);
|
|
break;
|
|
case RFtx:
|
|
case RFsendwor:
|
|
break;
|
|
}
|
|
|
|
if(RF.state <= RFidle)
|
|
symbols &= ~symbolRF;
|
|
else
|
|
symbols |= symbolRF;
|
|
|
|
VICSoftIntClr = INT_EINT0;
|
|
EXTINT = 0x01;
|
|
}
|
|
|
|
//********************
|
|
//* Public functions *
|
|
//********************
|
|
|
|
unsigned char RF_sendping(unsigned char dest) {
|
|
struct RFendpoint_* cur_ep;
|
|
|
|
cur_ep = openEP(0,0, packet_ping);
|
|
if(cur_ep) {
|
|
cur_ep->dest = dest;
|
|
cur_ep->data[0] = 1;
|
|
cur_ep->bufferlen = 1;
|
|
cur_ep->flags |= EPenabled | EPoutput | EPnewdata | EPonce | EPsendwor;
|
|
|
|
RF.flags &= ~PingACK;
|
|
RF_changestate(RFtx);
|
|
|
|
RF_timed_rx(WORrx_time);
|
|
|
|
while ((RF.timeout_cb != 0xff) && !(RF.flags & PingACK));
|
|
|
|
if(RF.flags & PingACK)
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void RF_init (void) {
|
|
cc1100_init();
|
|
RF.flags = 0;
|
|
RF.addr = conf[0x09];
|
|
RF.state = RFpwrdown;
|
|
RF.nextstate = RFpwrdown;
|
|
RF.timeout_cb = 0xff;
|
|
}
|
|
|
|
void RF_changestate (unsigned char state) {
|
|
unsigned char oldstate;
|
|
|
|
VICIntEnClr = INT_EINT0;
|
|
|
|
if(RF.state != state) {
|
|
oldstate = RF.state;
|
|
|
|
if((RF.state >= RFtx) && (state < RFtx)) {
|
|
RF.nextstate = state;
|
|
}
|
|
else {
|
|
switch (state) {
|
|
case RFpwrdown:
|
|
RF.state = RFpwrdown;
|
|
break;
|
|
case RFwor:
|
|
RF.state = RFwor;
|
|
RF.flags |= WORenabled;
|
|
break;
|
|
case RFidle:
|
|
RF.state = RFidle;
|
|
break;
|
|
case RFrx:
|
|
RF.state = RFrx;
|
|
break;
|
|
case RFtx:
|
|
if(RF.state < RFtx)
|
|
RF.state = RFtx;
|
|
if(oldstate == RFrx)
|
|
RF.nextstate = RFrx;
|
|
else if(RF.flags & WORenabled)
|
|
RF.nextstate = RFwor;
|
|
else
|
|
RF.nextstate = RFidle;
|
|
break;
|
|
case RFsendwor:
|
|
break;
|
|
}
|
|
}
|
|
if(oldstate != RF.state) {
|
|
VICSoftInt = INT_EINT0;
|
|
}
|
|
}
|
|
VICIntEnable = INT_EINT0;
|
|
}
|
|
|
|
void RF_timed_rx(unsigned short timeout) {
|
|
if (RF.timeout_cb != 0xff)
|
|
setCBIntervall(RF.timeout_cb,timeout);
|
|
else {
|
|
RF.timeout_cb = addTimerCB(RF_timed_rx_timeout, timeout);
|
|
startCB(RF.timeout_cb);
|
|
RF_changestate(RFrx);
|
|
}
|
|
}
|
|
|
|
void startRFIRQ(void) {
|
|
|
|
PINSEL1 |= 1; //GDO0 as EINT0
|
|
EXTMODE |= 1; //edge sensitive
|
|
EXTPOLAR |= 0; //falling edge
|
|
EXTWAKE |= 1;
|
|
EXTINT |= 1;
|
|
|
|
VICVectAddr2 = (unsigned long)&(cc1100IRQ);
|
|
VICVectCntl2 = VIC_SLOT_EN | INT_SRC_EINT0;
|
|
VICIntEnable = INT_EINT0;
|
|
}
|
|
|
|
void stopRFIRQ(void) {
|
|
VICIntEnClr = INT_EINT0;
|
|
}
|
|
|
|
|
|
struct RFendpoint_* openEP(void* buffer, unsigned short buffersize, unsigned char type) {
|
|
|
|
int i;
|
|
struct RFendpoint_* cur_ep;
|
|
|
|
if(!type)
|
|
return 0;
|
|
|
|
for(i=0; i<MAX_ENDPOINTS;i++) {
|
|
cur_ep = &rfendpoint[i];
|
|
if(!(cur_ep->type)) {
|
|
cur_ep->buffer = buffer;
|
|
cur_ep->buffersize = buffersize;
|
|
cur_ep->type = type;
|
|
cur_ep->bufferlen = 0;
|
|
cur_ep->dest = 0;
|
|
cur_ep->flags = 0;
|
|
if(!(buffer))
|
|
cur_ep->flags |= EPtypedata;
|
|
return cur_ep;
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
void closeEP(struct RFendpoint_ *cur_ep) {
|
|
if(cur_ep) {
|
|
cur_ep->flags = 0;
|
|
cur_ep->buffer = 0;
|
|
cur_ep->type = 0;
|
|
}
|
|
}
|
|
|
|
void RF_setRegister(unsigned char reg, unsigned char data) {
|
|
|
|
unsigned long VICInt;
|
|
|
|
VICInt = VICIntEnable & INT_EINT0;
|
|
VICIntEnClr = INT_EINT0;
|
|
|
|
cc1100_write1(reg,data);
|
|
|
|
VICIntEnable |= VICInt;
|
|
}
|
|
|
|
void load_RF_setting(void) {
|
|
struct RFsettings_ RFsettings;
|
|
|
|
if(BFS_LoadFile(BFS_ID_RFsettings, sizeof(struct RFsettings_), (unsigned char*) &RFsettings) != sizeof(struct RFsettings_)) {
|
|
RFsettings = default_RFsettings;
|
|
BFS_SaveFile(BFS_ID_RFsettings, sizeof(struct RFsettings_), (unsigned char*) &RFsettings);
|
|
draw_string(0, 50, "default RF load", 3, DRAW_PUT);
|
|
}
|
|
|
|
RF_setRegister(0x09, RFsettings.address);
|
|
RF_setRegister(0x0a, RFsettings.channel);
|
|
RF.addr = RFsettings.address;
|
|
}
|
|
|
|
|
|
void RFasyncmode(unsigned char on) {
|
|
|
|
if(on) {
|
|
RF_changestate(RFidle);
|
|
while(RF.state != RFidle);
|
|
stopRFIRQ();
|
|
cc1100_write((0x00 | BURST ),(unsigned char*)confasync,0x2f);
|
|
cc1100_write1(PATABLE,0xf0);
|
|
PINSEL1 &= 0xfffffffc; // GDO0 as GPIO
|
|
FIODIR0 |= GDO0; // output
|
|
}
|
|
else {
|
|
PINSEL1 |= 1; // GDO0 as EINT0
|
|
cc1100_write((0x00 | BURST ),(unsigned char*)conf,0x2f);
|
|
cc1100_write1(PATABLE,0xC0);
|
|
cc1100_strobe(SIDLE);
|
|
load_RF_setting();
|
|
startRFIRQ();
|
|
RF_changestate(RFwor);
|
|
}
|
|
}
|