📄 radioclient.c
字号:
/**
* Code to manage the client's radio transceiver.
* See main.c for a simple example of a basic client application.
*
* Read README for further documentation.
*
* Use at own risk, etc. Feel free to modify and distribute.
*
* @author Stephen Craig, 07/08/2006
*/
/* System macros (EXT_MODE, etc.) -- generated by 'gen_cpp_req_defines_h.tlc' */
#include "cpp_req_defines.h"
/* HAS_RFCOMMS: '0' : no RF communications, '1' : server, '2' : client, '3' : 'both' */
#if ((HAS_RFCOMMS == 2) | (HAS_RFCOMMS == 3))
/* ensure that SPI support is enabled */
#ifndef HAS_SPI
#define HAS_SPI 1
#endif
#include <mc9s12dp256.h> /* derivative information */
#include "radioClient.h" /* various macros etc */
//#include "sci0.h" /* support for SCI0 */
#include "rb_.h" /* ring buffer implementation */
#include "mc_timer.h" /* included for TIMER_PRESCALER */
/* define a macro to set the current module state */
#define setState(s) tickCounter = 0, moduleState = s
/* RF baud rate macro.
Include the macro for 1 MBits (may be necessary for large ranges)
Remove macro for 2 MBits */
// #define SLOW_RF_BAUD_RATE
#define CE PTM_PTM7 /* chip enable */
#define CE_DDR DDRM_DDRM7 /* chip enable data direction */
/* macro used to print out some debug info */
// #define TO_DEBUG
// #define TO_DEBUG_ERROR_CONDITIONS
#ifdef TO_DEBUG
#define TO_DEBUG_ERROR_CONDITIONS
#endif
#ifdef TO_DEBUG
/* when debugging, make the whole thing run as slow as possible */
#define TICK_PRESCALAR 0xffff
#define WAIT_FOR_ACK_TICK_COUNT 17
#else
#ifdef SLOW_RF_BAUD_RATE
/* For 1MBits, nominal time between T~ and ACK is given by
128 + 5 + 128 + 5 + 2*(33 + 33 + 4*(5 + 2 + PAYLOAD_LEN)) = 710us */
#define TICK_PRESCALAR (24*712/TIMER_PRESCALER)
/* If every packet fails, then MAX_RT will occur in
(250*1 + 8*(5+2+PAYLOAD_LEN) + 138.5)*16 = 12712us = 16 ticks
Make it 17 to be conservative */
#define WAIT_FOR_ACK_TICK_COUNT (17)
#else
/* For 2MBits, nominal time between T~ and ACK is given by
128 + 5 + 128 + 5 + 1*(33 + 33 + 4*(5 + 2 + PAYLOAD_LEN)) = 488us */
#define TICK_PRESCALAR (24*490/TIMER_PRESCALER)
/* If every packet fails, then MAX_RT will occur in
(250*1 + 4*(5+2+PAYLOAD_LEN) + 138.5)*16 = 8712us = 18 ticks
Make it 19 to be conservative */
#define WAIT_FOR_ACK_TICK_COUNT (19)
#endif
#endif
#define TIME_OUT_TICK_COUNT (255)
#define TICK_REGISTER TC0
#define TICK_ENABLE TIE_C0I
#define TICK_INTERRUPT TFLG1_C0F
// RadioClient_OnTick
/* a delay is required for the client to enter receive mode */
#define WAIT_FOR_SERVER_TICK_COUNT 1
#define ADDRESS_LENGTH 5 /* Address length (should be 5) */
/* define useful mnemonics */
/* these are all reads */
#define R_CONFIG 0x00 // Configuration Register
#define R_EN_AA 0x01 // Enable Auto Acknowledge
#define R_EN_RXADDR 0x02 // Enable RX Addresses
#define R_SETUP_AW 0x03 // Setup of Address Widths
#define R_SETUP_RETR 0x04 // Setup of Automatic Retransmission
#define R_RF_CH 0x05 // RF Channel
#define R_RF_SETUP 0x06 // RF Setup
#define R_STATUS 0x07 // Status
#define R_OBSERVE_TX 0x08 // Transmit Observe register
#define R_CD 0x09 // Carrier Detect
#define R_RX_ADDR_P0 0x0a // Receive address data pipe 0
#define R_RX_ADDR_P1 0x0b // Receive address data pipe 1
#define R_RX_ADDR_P2 0x0c // Receive address data pipe 2
#define R_RX_ADDR_P3 0x0d // Receive address data pipe 3
#define R_RX_ADDR_P4 0x0e // Receive address data pipe 4
#define R_RX_ADDR_P5 0x0f // Receive address data pipe 5
#define R_TX_ADDR 0x10 // Transmit address
#define R_RX_PW_0 0x11 // Number of bytes in RX payload for pipe 0
#define R_RX_PW_1 0x12 // Number of bytes in RX payload for pipe 1
#define R_RX_PW_2 0x13 // Number of bytes in RX payload for pipe 2
#define R_RX_PW_3 0x14 // Number of bytes in RX payload for pipe 3
#define R_RW_PW_4 0x15 // Number of bytes in RX payload for pipe 4
#define R_RW_PW_5 0x16 // Number of bytes in RX payload for pipe 5
#define R_FIFO_STATUS 0x17 // FIFO Status register
/* these are all writes */
#define W_CONFIG 0x20 // Configuration Register
#define W_EN_AA 0x21 // Enable Auto Acknowledge
#define W_EN_RXADDR 0x22 // Enable RX Addresses
#define W_SETUP_AW 0x23 // Setup of Address Widths
#define W_SETUP_RETR 0x24 // Setup of Automatic Retransmission
#define W_RF_CH 0x25 // RF Channel
#define W_RF_SETUP 0x26 // RF Setup
#define W_STATUS 0x27 // Status
#define W_OBSERVE_TX 0x28 // Transmit Observe register
#define W_RX_ADDR_P0 0x2a // Receive address data pipe 0
#define W_RX_ADDR_P1 0x2b // Receive address data pipe 1
#define W_RX_ADDR_P2 0x2c // Receive address data pipe 2
#define W_RX_ADDR_P3 0x2d // Receive address data pipe 3
#define W_RX_ADDR_P4 0x2e // Receive address data pipe 4
#define W_RX_ADDR_P5 0x2f // Receive address data pipe 5
#define W_TX_ADDR 0x30 // Transmit address
#define W_RX_PW_0 0x31 // Number of bytes in RX payload for pipe 0
#define W_RX_PW_1 0x32 // Number of bytes in RX payload for pipe 1
#define W_RX_PW_2 0x33 // Number of bytes in RX payload for pipe 2
#define W_RX_PW_3 0x34 // Number of bytes in RX payload for pipe 3
#define W_RX_PW_4 0x35 // Number of bytes in RX payload for pipe 4
#define W_RX_PW_5 0x36 // Number of bytes in RX payload for pipe 5
#define R_RX_PAYLOAD 0x61 // Read RX-payload
#define W_TX_PAYLOAD 0xa0 // Write TX-payload
#define FLUSH_TX 0xe1 // Flush transmit buffer
#define FLUSH_RX 0xe2 // Flush receive buffer
#define REUSE_TX_PL 0xe3 // Reuse last transmission
#define NOP 0xff // No operation
/* Flags in STATUS */
#define RX_DR_MASK 0x40 /* Data Ready RX FIFO interrupt */
#define TX_DS_MASK 0x20 /* Data Sent TX FIFO interrupt */
#define MAX_RT_MASK 0x10 /* Max number of TX retries interrupt */
#define RX_P_NO_MASK 0x0e /* Mask to retrieve the data pipe number */
#define RX_EMPTY_MASK 0x01 /* Flag in FIFO_STATUS register */
#define RF_CH_MASK 0x7f /* To ensure 0 < rf_ch < 127 */
/* used to escape the characters matching the EOT token and ESCAPE */
#define RADIO_ESCAPE_CHAR 0xfe
/* end of transmission token */
#define RADIO_EOT_CHAR 0xfd
/* define states */
#define STATE_WAIT_FOR_EOT 0
#define STATE_WAIT_FOR_RECEIVE 1
#define STATE_WAIT_FOR_SERVER 2
/* First byte of every message is a header byte */
/* This flag is set if the client (or server) has been reset. */
#define HEADER_RESET_MASK 0x80
/* This flag is set if the client (or server) acknowledges reset. */
#define HEADER_ACK_RESET_MASK 0x40
/* This bit is set in the header byte if the header is to be
interpretted as EOT */
#define HEADER_EOT_MASK 0x10
/* Last byte of client 0's address, etc
Must match the address specified in radioClient.c */
#define CLIENT_TAIL_0 0xc2
#define CLIENT_TAIL_1 0xc3
#define CLIENT_TAIL_2 0xc4
#define CLIENT_TAIL_3 0xc5
#define CLIENT_TAIL_4 0xc6
#define RB_TX_FULL(b) \
( ((unsigned char)((b)->out - (b)->in) <= PAYLOAD_LEN - 3) \
&& ((b)->in != (b)->out) \
)
#define RB_TX_PUSH(b, v) \
(RB_TX_FULL(b) ? 1 : \
((b)->start[(b)->in++] = (v), (b)->nElements++, 0) \
)
typedef struct {
/* the index of the state in the commStates array */
unsigned char id;
/* memory for outgoing data, has to be 256 bytes */
unsigned char outBuf[256];
/* memory for incoming data, has to be 256 bytes */
unsigned char inBuf[256];
/* declare pointers to rb data structures */
rbType outRB;
rbType inRB;
/* store the last tID sent here */
unsigned char lastTID;
/* flags to store reset status */
unsigned char reset;
unsigned short failureCount;
} commStateType;
commStateType commState;
commStateType *cc = NULL;
/* store the current state */
unsigned char moduleState;
/* incremented every time there is a tick */
unsigned char tickCounter;
/*
Transmit() is a private procedure that is only called when the
client is in possession of the EOT token.
*/
void RadioClient_Transmit() {
unsigned char i, haveSentEOT, header, data;
#ifdef TO_DEBUG
SCI0_OutString("T\r\n"); /* enter Transmit */
#endif
/* can only re-configure if in stand-by mode */
CE = 0;
/* a good idea to clear all interrupts and flush buffers first */
SPI_OutChar(FLUSH_TX);
SPI_OutChar(FLUSH_RX);
/* clears all interrupts */
SPI_OutChar2(W_STATUS, RX_DR_MASK | TX_DS_MASK | MAX_RT_MASK);
/*
bit CONFIG Register
7 0 Reserved
6 1 MASK_RX_DR : Don't reflect RX_DR on IRQ pin
5 1 MASK_TX_DS : Don't reflect TX_DS on IRQ pin
4 1 MASK_MAX_RT : Don't reflect MAX_RT on IRQ pin
3 1 EN_CRC : Enable CRC
2 1 CRCO : 2 byte CRC
1 1 PWR_UP : Power Up
0 0 PRIM_RX : PTX
Enter transmit mode
*/
SPI_OutChar2(W_CONFIG, 0x7e);
/* download the next segment */
while(SPI0SR_SPTEF == 0) {}
/* begin SPI segment */
CSN = 0;
/* output the write transmit buffer command */
SPI0DR = W_TX_PAYLOAD;
SPI_Pause();
/* Determine what the header byte should be */
header = cc->reset;
if(header & HEADER_RESET_MASK) {
/* if we've reset recently, make sure we start transmitting
from the start of the transmit buffer */
RB_SET_OUT(&cc->outRB, 0);
header |= HEADER_EOT_MASK;
}
/* determine whether we should send EOT in header byte */
if(RB_EMPTY(&cc->outRB)) {
header |= HEADER_EOT_MASK;
}
/* output the header byte */
while(SPI0SR_SPTEF == 0) {}
SPI0DR = header;
SPI_Pause();
/* work out if EOT was set in header */
haveSentEOT = (header & HEADER_EOT_MASK) != 0;
/* output the rID */
while(SPI0SR_SPTEF == 0) {}
SPI0DR = cc->inRB.in;
SPI_Pause();
/* output the tID */
while(SPI0SR_SPTEF == 0) {}
SPI0DR = cc->outRB.out;
SPI_Pause();
/* store what the last tID sent was */
cc->lastTID = cc->outRB.out;
/* fill the remaining 31 bytes */
for(i=3; i<PAYLOAD_LEN; i++) {
while(SPI0SR_SPTEF == 0) {}
if(haveSentEOT == 0) {
if(RB_EMPTY(&cc->outRB)) {
/* if there's no more data to be sent, then EOT */
SPI0DR = RADIO_EOT_CHAR;
haveSentEOT = 1;
} else {
/* check what the next byte is to send */
RB_PEEK(&cc->outRB, &data);
if(data != RADIO_ESCAPE_CHAR
&& data != RADIO_EOT_CHAR) {
/* the byte is not a special token, transmit it */
RB_POP(&cc->outRB, &SPI0DR);
} else {
/* the data to be sent matches a special token, need to
escape the data to be sent so it doesn't get
misinterpretted */
if(i == PAYLOAD_LEN - 1) {
/* there's not enough space for the ESCAPE token and
the escaped char in this segment,
=> EOT, send the character next time */
SPI0DR = RADIO_EOT_CHAR;
haveSentEOT = 1;
} else {
/* there is space for the ESCAPE token and the escaped
char */
SPI0DR = RADIO_ESCAPE_CHAR;
SPI_Pause();
while(SPI0SR_SPTEF == 0) {}
RB_POP(&cc->outRB, &SPI0DR);
i++;
}
}
}
} else {
/* we have sent EOT, but still need to fill tx_payload */
/* fill the rest of the transmit buffer with \0 */
SPI0DR = 0x00;
}
SPI_Pause();
}
/* end SPI packet */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -