📄 cc1000radiointm.nc
字号:
RadioState = IDLE_STATE;
bTxPending = bTxBusy = FALSE;
sMacDelay = -1;
preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8) |
PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1]));
}
if (lplpower == 0) {
// all power on, captain!
rxbufptr->length = 0;
atomic RadioState = IDLE_STATE;
call CC1000StdControl.start();
call CC1000Control.BIASOn();
call SpiByteFifo.rxMode(); // SPI to miso
call CC1000Control.RxMode();
if (iSquelchCount > CC1K_SquelchCount)
call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
else
call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
call SpiByteFifo.enableIntr(); // enable spi interrupt
}
else {
uint16_t sleeptime = ((PRG_RDB(&CC1K_LPL_SleepTime[lplpower*2]) << 8) |
PRG_RDB(&CC1K_LPL_SleepTime[(lplpower*2)+1]));
atomic RadioState = POWER_DOWN_STATE;
call TimerControl.start();
call SquelchTimer.stop();
call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
}
}
return SUCCESS;
}
command result_t Send.send(TOS_MsgPtr pMsg) {
result_t Result = SUCCESS;
uint8_t currentRadioState = 0;
atomic {
if (bTxBusy) {
Result = FAIL;
}
else {
bTxBusy = TRUE;
txbufptr = pMsg;
txbufptr->ack = 0;
txlength = pMsg->length + (MSG_DATA_SIZE - DATA_LENGTH - 2);
// initially back off [1,32] bytes (approx 2/3 packet)
sMacDelay = signal MacBackoff.initialBackoff(pMsg);
bTxPending = TRUE;
}
currentRadioState = RadioState;
}
if (Result) {
// if we're off, start the radio
if (currentRadioState == POWER_DOWN_STATE) {
// disable wakeup timer
call WakeupTimer.stop();
call CC1000StdControl.start();
call CC1000Control.BIASOn();
call CC1000Control.RxMode();
call SpiByteFifo.rxMode(); // SPI to miso
call SpiByteFifo.enableIntr(); // enable spi interrupt
if (iSquelchCount > CC1K_SquelchCount)
call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
else
call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_LPL_PACKET_TIME*2);
atomic RadioState = IDLE_STATE;
}
}
return Result;
}
/**********************************************************
* make a spibus interrupt handler
* needs to handle interrupts for transmit delay
* and then go into byte transmit mode with
* timer1 baudrate delay as interrupt handler
* else
* needs to handle interrupts for byte read and detect preamble
* then handle reading a packet
* PB - We can use this interrupt handler as a transmit scheduler
* because the CC1000 continuously clocks in data, regarless
* of whether it's good or not. Thus, this routine will be called
* on every 8 ticks of DCLK.
**********************************************************/
async event result_t SpiByteFifo.dataReady(uint8_t data_in) {
signal RadioSendCoordinator.blockTimer();
signal RadioReceiveCoordinator.blockTimer();
if (bInvertRxData)
data_in = ~data_in;
#ifdef ENABLE_UART_DEBUG
UARTPutChar(RadioState);
#endif
switch (RadioState) {
case TX_STATE:
{
call SpiByteFifo.writeByte(NextTxByte);
TxByteCnt++;
switch (RadioTxState) {
case TXSTATE_PREAMBLE:
if (!(TxByteCnt < preamblelen)) {
NextTxByte = SYNC_BYTE;
RadioTxState = TXSTATE_SYNC;
}
break;
case TXSTATE_SYNC:
NextTxByte = NSYNC_BYTE;
RadioTxState = TXSTATE_DATA;
TxByteCnt = -1;
// for Time Sync services
signal RadioSendCoordinator.startSymbol(8, 0, txbufptr);
break;
case TXSTATE_DATA:
if ((uint8_t)(TxByteCnt) < txlength) {
NextTxByte = ((uint8_t *)txbufptr)[(TxByteCnt)];
usRunningCRC = crcByte(usRunningCRC,NextTxByte);
// Time Sync
signal RadioSendCoordinator.byte(txbufptr, (uint8_t)TxByteCnt);
}
else {
NextTxByte = (uint8_t)(usRunningCRC);
RadioTxState = TXSTATE_CRC;
}
break;
case TXSTATE_CRC:
NextTxByte = (uint8_t)(usRunningCRC>>8);
RadioTxState = TXSTATE_FLUSH;
TxByteCnt = 0;
break;
case TXSTATE_FLUSH:
if (TxByteCnt > 3) {
if ((bAckEnable) && (txbufptr->addr != TOS_BCAST_ADDR)) {
TxByteCnt = 0;
RadioTxState = TXSTATE_WAIT_FOR_ACK;
}
else {
RadioTxState = TXSTATE_DONE;
}
}
break;
case TXSTATE_WAIT_FOR_ACK:
if(TxByteCnt == 1){
call SpiByteFifo.rxMode();
call CC1000Control.RxMode();
}
if (TxByteCnt > 3) {
RadioTxState = TXSTATE_READ_ACK;
TxByteCnt = 0;
search_word = 0;
}
break;
case TXSTATE_READ_ACK:
{
uint8_t i;
for(i = 0; i < 8; i ++){
search_word <<= 1;
if(data_in & 0x80) search_word |= 0x1;
data_in <<= 1;
if (search_word == 0xba83){
txbufptr->ack = 1;
RadioTxState = TXSTATE_DONE;
return SUCCESS;
}
}
}
if(TxByteCnt == MAX_ACK_WAIT){
txbufptr->ack = 0;
RadioTxState = TXSTATE_DONE;
}
break;
case TXSTATE_DONE:
default:
bTxPending = FALSE;
if (post PacketSent()) {
// If the post operation succeeds, goto Idle
// otherwise, we'll try again.
call SpiByteFifo.rxMode();
call CC1000Control.RxMode();
RadioState = IDLE_STATE;
RSSIInitState = RadioState;
call RSSIADC.getData();
}
break;
}
}
break;
case DISABLED_STATE:
break;
case IDLE_STATE:
{
if (((data_in == (0xaa)) || (data_in == (0x55)))) {
PreambleCount++;
if (PreambleCount > CC1K_ValidPrecursor) {
PreambleCount = SOFCount = 0;
RxBitOffset = RxByteCnt = 0;
usRunningCRC = 0;
rxlength = MSG_DATA_SIZE-2;
RadioState = SYNC_STATE;
}
}
else if (bTxPending && (--sMacDelay <= 0)) {
RadioState = PRETX_STATE;
RSSIInitState = PRETX_STATE;
iRSSIcount = 0;
PreambleCount = 0;
call RSSIADC.getData();
}
}
break;
case PRETX_STATE:
{
if (((data_in == (0xaa)) || (data_in == (0x55)))) {
// Back to the penalty box.
sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
RadioState = IDLE_STATE;
}
}
break;
case SYNC_STATE:
{
// draw in the preamble bytes and look for a sync byte
// save the data in a short with last byte received as msbyte
// and current byte received as the lsbyte.
// use a bit shift compare to find the byte boundary for the sync byte
// retain the shift value and use it to collect all of the packet data
// check for data inversion, and restore proper polarity
// XXX-PB: Don't do this.
uint8_t i;
if ((data_in == 0xaa) || (data_in == 0x55)) {
// It is actually possible to have the LAST BIT of the incoming
// data be part of the Sync Byte. SO, we need to store that
// However, the next byte should definitely not have this pattern.
// XXX-PB: Do we need to check for excessive preamble?
RxShiftBuf.MSB = data_in;
}
else {
// TODO: Modify to be tolerant of bad bits in the preamble...
uint16_t usTmp;
switch (SOFCount) {
case 0:
RxShiftBuf.LSB = data_in;
break;
case 1:
case 2:
// bit shift the data in with previous sample to find sync
usTmp = RxShiftBuf.W;
RxShiftBuf.W <<= 8;
RxShiftBuf.LSB = data_in;
for(i=0;i<8;i++) {
usTmp <<= 1;
if(data_in & 0x80)
usTmp |= 0x1;
data_in <<= 1;
// check for sync bytes
if (usTmp == SYNC_WORD) {
if (rxbufptr->length !=0) {
call Leds.redToggle();
RadioState = IDLE_STATE;
}
else {
RadioState = RX_STATE;
RSSIInitState = RX_STATE;
call RSSIADC.getData();
RxBitOffset = 7-i;
// For time sync services
signal RadioReceiveCoordinator.startSymbol(8, RxBitOffset, rxbufptr);
}
break;
}
}
break;
default:
// We didn't find it after a reasonable number of tries, so....
RadioState = IDLE_STATE; // Ensures we wait till the end of the transmission
break;
}
SOFCount++;
}
}
break;
// collect the data and shift into double buffer
// shift out data by correct offset
// invert the data if necessary
// stop after the correct packet length is read
// return notification to upper levels
// go back to idle state
case RX_STATE:
{
char Byte;
RxShiftBuf.W <<=8;
RxShiftBuf.LSB = data_in;
Byte = (RxShiftBuf.W >> RxBitOffset);
((char*)rxbufptr)[(int)RxByteCnt] = Byte;
RxByteCnt++;
// Time Sync: substract one to start counting from zero
signal RadioReceiveCoordinator.byte(rxbufptr, (uint8_t)RxByteCnt-1);
if (RxByteCnt < rxlength) {
usRunningCRC = crcByte(usRunningCRC,Byte);
if (RxByteCnt == (offsetof(struct TOS_Msg,length) +
sizeof(((struct TOS_Msg *)0)->length))) {
rxlength = rxbufptr->length;
if (rxlength > TOSH_DATA_LENGTH) {
// The packet's screwed up, so just dump it
rxbufptr->length = 0;
RadioState = IDLE_STATE; // Waits till end of transmission
return SUCCESS;
}
//Add in the header size
rxlength += offsetof(struct TOS_Msg,data);
if (rxbufptr->length == 0) {
RxByteCnt = offsetof(struct TOS_Msg,crc);
}
}
}
else if (RxByteCnt == rxlength) {
usRunningCRC = crcByte(usRunningCRC,Byte);
// Shift index ahead to the crc field.
RxByteCnt = offsetof(struct TOS_Msg,crc);
}
else if (RxByteCnt >= MSG_DATA_SIZE) {
// Packet filtering based on bad CRC's is done at higher layers.
// So sayeth the TOS weenies.
if (rxbufptr->crc == usRunningCRC) {
rxbufptr->crc = 1;
if (bAckEnable) {
if (rxbufptr->addr == TOS_LOCAL_ADDRESS) {
RadioState = SENDING_ACK;
call CC1000Control.TxMode();
call SpiByteFifo.txMode();
call SpiByteFifo.writeByte(0xaa);
RxByteCnt = 0;
return SUCCESS;
}
}
} else {
rxbufptr->crc = 0;
}
call SpiByteFifo.disableIntr();
RadioState = IDLE_STATE; //DISABLED_STATE;
rxbufptr->strength = usRSSIVal;
if (!(post PacketRcvd())) {
// If there are insufficient resources to process the incoming packet
// we drop it
rxbufptr->length = 0;
RadioState = IDLE_STATE;
call SpiByteFifo.enableIntr();
}
}
}
break;
case SENDING_ACK:
{
RxByteCnt++;
if (RxByteCnt >= ACK_LENGTH) {
call CC1000Control.RxMode();
call SpiByteFifo.rxMode();
call SpiByteFifo.disableIntr();
RadioState = IDLE_STATE; //DISABLED_STATE;
rxbufptr->strength = usRSSIVal;
if (!(post PacketRcvd())) {
rxbufptr->length = 0;
RadioState = IDLE_STATE;
call SpiByteFifo.enableIntr();
}
}else if(RxByteCnt >= ACK_LENGTH - sizeof(ack_code) - 2){
call SpiByteFifo.writeByte(ack_code[RxByteCnt + sizeof(ack_code) + 2- ACK_LENGTH]);
}
}
break;
default:
break;
}
return SUCCESS;
}
async event result_t RSSIADC.dataReady(uint16_t data) {
uint8_t currentRadioState;
uint8_t initRSSIState;
atomic {
currentRadioState = RadioState;
initRSSIState = RSSIInitState;
}
// find the maximum RSSI value over CC1K_MAX_RSSI_SAMPLES
switch(currentRadioState) {
case IDLE_STATE:
if (initRSSIState == IDLE_STATE) {
atomic usTempSquelch = data;
post adjustSquelch();
}
atomic RSSIInitState = NULL_STATE;
break;
case RX_STATE:
if (initRSSIState == RX_STATE) {
atomic usRSSIVal = data;
}
atomic RSSIInitState = NULL_STATE;
break;
case PRETX_STATE:
iRSSIcount++;
// if the channel is clear, GO GO GO!
if ((data > (usSquelchVal + CC1K_SquelchBuffer)) && (initRSSIState == PRETX_STATE)) {
call SpiByteFifo.writeByte(0xaa);
call CC1000Control.TxMode();
call SpiByteFifo.txMode();
atomic {
usRSSIVal = data;
iRSSIcount = CC1K_MaxRSSISamples;
TxByteCnt = 0;
usRunningCRC = 0;
RadioState = TX_STATE;
RadioTxState = TXSTATE_PREAMBLE;
NextTxByte = 0xaa;
RSSIInitState = NULL_STATE;
}
return SUCCESS;
}
atomic RSSIInitState = NULL_STATE;
if (iRSSIcount == CC1K_MaxRSSISamples) {
atomic {
sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
RadioState = IDLE_STATE;
}
}
else {
atomic RSSIInitState = currentRadioState;
call RSSIADC.getData();
}
break;
default:
}
return SUCCESS;
}
async command void MacControl.enableAck() {
bAckEnable = TRUE;
}
async command void MacControl.disableAck() {
bAckEnable = FALSE;
}
// XXX:JP- for testing the mac layer squlech value
command uint16_t GetSquelch() {
return usSquelchVal;
}
// Default events for radio send/receive coordinators do nothing.
// Be very careful using these, you'll break the stack.
default async event void RadioSendCoordinator.startSymbol(uint8_t bitsPerBlock, uint8_t offset, TOS_MsgPtr msgBuff) { }
default async event void RadioSendCoordinator.byte(TOS_MsgPtr msg, uint8_t byteCount) { }
default async event void RadioSendCoordinator.blockTimer() { }
default async event void RadioReceiveCoordinator.startSymbol(uint8_t bitsPerBlock, uint8_t offset, TOS_MsgPtr msgBuff) { }
default async event void RadioReceiveCoordinator.byte(TOS_MsgPtr msg, uint8_t byteCount) { }
default async event void RadioReceiveCoordinator.blockTimer() { }
default async event int16_t MacBackoff.initialBackoff(TOS_MsgPtr m) {
return (call Random.rand() & 0x1F) + 1;
// return 0;
}
default async event int16_t MacBackoff.congestionBackoff(TOS_MsgPtr m) {
return (call Random.rand() & 0xF) + 1;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -