Skip to content

Commit

Permalink
Working RF TX and RX on 2 sets of OBC and RF boards
Browse files Browse the repository at this point in the history
Setup:
- OBC/RF board set 1 compiled with STX strobe in rfTxTestSequence().
- OBC/RF board set 2 compiled with SRX strobe in rfTxTestSequence().
- In UART prompt, enter on both sets: > task resume 10
- Set 1 sample output:
...
radio task (0x0)
S 0x3d
 < 0x0f
tx_underflowed:no tx_numbytes:0
S 0x3d
 < 0x0f
TX FIFO_BYTES_AVAILABLE: 0xf
S 0xbd
 < 0x00
RX FIFO_BYTES_AVAILABLE: 0x0
S 0x3d
 < 0x0f
62 Bytes Radio TX FIFO written
AFTER: tx_underflowed:no tx_numbytes:62
S 0x35
 < 0x02
STX strobed...
S 0x3d
 < 0x24
StatusByte: 0x24
radio task (0x0)
S 0x3d
 < 0x0f
tx_underflowed:no tx_numbytes:0
S 0x3d
 < 0x0f
TX FIFO_BYTES_AVAILABLE: 0xf
S 0xbd
 < 0x00
RX FIFO_BYTES_AVAILABLE: 0x0
S 0x3d
 < 0x0f
62 Bytes Radio TX FIFO written
AFTER: tx_underflowed:no tx_numbytes:62
S 0x35
 < 0x02
STX strobed...
S 0x3d
 < 0x24
StatusByte: 0x24
radio task (0x0)
S 0x3d
 < 0x0f
tx_underflowed:no tx_numbytes:0
S 0x3d
 < 0x0f
TX FIFO_BYTES_AVAILABLE: 0xf
S 0xbd
 < 0x00
RX FIFO_BYTES_AVAILABLE: 0x0
S 0x3d
 < 0x0f
62 Bytes Radio TX FIFO written
AFTER: tx_underflowed:no tx_numbytes:62
S 0x35
 < 0x02
STX strobed...
S 0x3d
 < 0x24
StatusByte: 0x24

- Set 2 sample output:
...
radio task (0x0)
S 0x3d
< 0x02
tx_underflowed:no tx_numbytes:62
S 0x3d
< 0x02
TX FIFO_BYTES_AVAILABLE: 0x2
S 0xbd
< 0x0f
RX FIFO_BYTES_AVAILABLE: 0xf
S 0x3d
< 0x02
Radio did not write
AFTER: tx_underflowed:no tx_numbytes:62
S 0x34
< 0x02
STX strobed...
S 0x3d
< 0x12
StatusByte: 0x12
RX Byte #0: 3e
RX Byte #1: 10
RX Byte #2: 02
RX Byte #3: 03
RX Byte #4: 04
RX Byte #5: 05
RX Byte #6: 06
RX Byte #7: 07
RX Byte #8: 08
RX Byte #9: 09
RX Byte #10: 0a
RX Byte #11: 0b
RX Byte #12: 0c
RX Byte #13: 0d
RX Byte #14: 0e
RX Byte #15: 0f
RX Byte #16: 10
RX Byte #17: 11
RX Byte #18: 12
RX Byte #19: 13
RX Byte #20: 14
RX Byte #21: 15
RX Byte #22: 16
RX Byte #23: 17
RX Byte #24: 18
RX Byte #25: 19
RX Byte #26: 1a
RX Byte #27: 1b
RX Byte #28: 1c
RX Byte #29: 1d
RX Byte #30: 1e
RX Byte #31: 1f
RX Byte #32: 20
RX Byte #33: 21
RX Byte #34: 22
RX Byte #35: 23
RX Byte #36: 24
RX Byte #37: 25
RX Byte #38: 26
RX Byte #39: 27
RX Byte #40: 28
RX Byte #41: 29
RX Byte #42: 2a
RX Byte #43: 2b
RX Byte #44: 2c
RX Byte #45: 2d
RX Byte #46: 2e
RX Byte #47: 2f
RX Byte #48: 30
RX Byte #49: 31
RX Byte #50: 32
RX Byte #51: 33
RX Byte #52: 34
RX Byte #53: 35
RX Byte #54: 36
RX Byte #55: 37
RX Byte #56: 38
RX Byte #57: 39
RX Byte #58: 3a
RX Byte #59: 3b
RX Byte #60: 3c
RX Byte #61: 3d
RX Byte #62: e8
RX Byte #63: ba

Misc:
- Fix calculation of fifo bytes in writeToTxFIFO.
- TODO: readFromRxFIFO changed to always queuering FIFO_RX; change to check only when needed.
- Create IS_STATE macro to check state easily.
  • Loading branch information
liquiddandruff committed Jun 10, 2018
1 parent db957df commit ed43414
Showing 1 changed file with 143 additions and 81 deletions.
224 changes: 143 additions & 81 deletions SFUsat/sfu_task_radio.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ const uint16 SMARTRF_VALS_TX[NUM_CONFIG_REGISTERS] = {
/**
* Chip Status Byte Masks (section 10.1, page 31).
*
* Use the IS_STATE macro below to check state.
*
* Status mask:
* - (mask of flag << overlay mask on uint8). The shift is done this way to aid in readability.
* State mask:
Expand All @@ -140,6 +142,16 @@ const uint16 SMARTRF_VALS_TX[NUM_CONFIG_REGISTERS] = {
#define STATE_RXFIFO_OVERFLOW (0b110) // RX FIFO has overflowed. Read out any useful data, then flush the FIFO with SFRX.
#define STATE_TXFIFO_UNDERFLOW (0b111) // TX FIFO has underflowed. Acknowledge with SFTX.
#define FIFO_BYTES_AVAILABLE (0b1111 << 0) // Bits 3:0 The number of bytes available in the RX FIFO or free bytes in the TX FIFO.
/**
* Macro to easily check state from statusByte.
*
* Assumes statusByte is defined and up-to-date.
* Strobe a NOP with strobe(SNOP) to update statusByte.
*
* Example:
* - if ( IS_STATE(STATE_IDLE) ) { // in STATE_IDLE }
*/
#define IS_STATE(x) ( (statusByte & STATE) >> 4 == (x) )

/**
* Command Strobe Registers (section 29.0, page 67).
Expand Down Expand Up @@ -175,6 +187,7 @@ const uint16 SMARTRF_VALS_TX[NUM_CONFIG_REGISTERS] = {
#define RXBYTES (0x3B | BURST_BIT) // Overflow and number of bytes.
#define RCCTRL1_STATUS (0x3C | BURST_BIT) // High byte of last RC oscillator calibration result.
#define RCCTRL0_STATUS (0x3D | BURST_BIT) // Low byte of last RC oscillator calibration result.
#define NUM_STATUS_REGISTERS (14)

/**
* Status Register Masks (section 29.3, page 94).
Expand Down Expand Up @@ -218,8 +231,11 @@ typedef struct RadioDAT {
* Forward declarations
*/
static uint8 readRegister(uint8 addr);
static int readFromRxFIFO(uint8 *dest, uint8 size);
static int readFromRxFIFO(uint8 *dest, uint8 numBytesToRead);
static void strobe(uint8 addr);
static uint8 * readAllStatusRegisters();
static void rfTxTestSequence();
static void printStatusByte();

//Declarations for RF Interrupt
SemaphoreHandle_t gioRFSem;
Expand All @@ -229,6 +245,8 @@ void vRadioTask(void *pvParameters) {
xRadioTXQueue = xQueueCreate(10, sizeof(portCHAR *));
xRadioRXQueue = xQueueCreate(10, sizeof(portCHAR));

char *txCurrQueuedStr = NULL;

initRadio();

strobe(SRX);
Expand All @@ -248,68 +266,109 @@ void vRadioTask(void *pvParameters) {
case 0xBEEFDEAD: {
spiEnableLoopback(RF_SPI_REG, Analog_Lbk);
break;
}
case 0xDEADBEEF: {
} case 0xDEADBEEF: {
spiDisableLoopback(RF_SPI_REG);
break;
} case 0x1: {
rfTxTestSequence();
break;
}
}
serialSendln(buffer);

//uint8 test[] = {0, 3, 9, 27, 14, 15, 16, 17, 18, 19};
uint8 packetLen = 3;
uint8 test[100] = { 0 };
int i = 2;
test[0] = packetLen;
test[1] = 0x10;
while (i < packetLen) {
test[i] = i;
i++;
}

uint8 txbytes = readRegister(TXBYTES);
uint8 tx_underflowed = txbytes & TXFIFO_UNDERFLOW;
uint8 tx_numbytes = txbytes & NUM_TXBYTES;
snprintf(buffer, sizeof(buffer), "tx_underflowed:%s tx_numbytes:%d", tx_underflowed ? "yes" : "no", tx_numbytes);
serialSendln(buffer);

strobe(SNOP);
serialSend("TX FIFO_BYTES_AVAILABLE: ");
snprintf(buffer, sizeof(buffer), "0x%x 0d%d", statusByte & FIFO_BYTES_AVAILABLE, statusByte & FIFO_BYTES_AVAILABLE);
serialSendln(buffer);
rfTxTestSequence();

strobe(SNOP | READ_BIT);
serialSend("RX FIFO_BYTES_AVAILABLE: ");
snprintf(buffer, sizeof(buffer), "0x%x 0d%d", statusByte & FIFO_BYTES_AVAILABLE, statusByte & FIFO_BYTES_AVAILABLE);
serialSendln(buffer);
// uint8 *stat = readAllStatusRegisters();
// serialSend("status registers\n");
// int temp = 0;
// for ( i = 0; i < NUM_STATUS_REGISTERS; i++ ) {
// temp += snprintf(buffer + temp, sizeof(buffer), "%d: %02x\n", i, stat[i]);
// }
// serialSend(buffer);

if (1) { //1 for tx
/**
* Strobe a NOP to ensure last operation was a write.
* Then statusByte will be primed with FIFO_BYTES_AVAILABLE for TX FIFO.
*/
strobe(SNOP);
if (writeToTxFIFO(test, packetLen)) {
snprintf(buffer, sizeof(buffer), "%d Bytes Radio TX FIFO written", packetLen);
serialSendln(buffer);
} else {
snprintf(buffer, sizeof(buffer), "Radio did not write");
serialSendln(buffer);
}

strobe(STX);
}
vTaskDelay(pdMS_TO_TICKS(5000)); // do we need this?
}
}

//TODO: use timer and return timeout error if radio never returns to IDLE, this should be done for most state transitions
if(readRegister(RXBYTES) != 0){
readFromRxFIFO(test, 5);
snprintf(buffer, sizeof(buffer), "RX: %02x %02x %02x %02x %02x", test[0], test[1], test[2], test[3], test[4]);
serialSendln(buffer);
}
static void rfTxTestSequence() {
strobe(SNOP);
// strobe(SIDLE);
// strobe(SFTX);
char buffer[100] = {'\0'};
uint8 packetLen = 62;
uint8 test[100] = { 0 };
int i = 2;
test[0] = packetLen;
test[1] = 0x10;
while (i < packetLen) {
test[i] = i;
i++;
}
uint8 txbytes = readRegister(TXBYTES);
uint8 tx_underflowed = txbytes & TXFIFO_UNDERFLOW;
uint8 tx_numbytes = txbytes & NUM_TXBYTES;
snprintf(buffer, sizeof(buffer), "tx_underflowed:%s tx_numbytes:%d", tx_underflowed ? "yes" : "no", tx_numbytes);
serialSendln(buffer);

if (IS_STATE(STATE_TXFIFO_UNDERFLOW)) {
serialSendln("TX Underflowed; Strobing SFTX...");
strobe(SFTX);
} else if (IS_STATE(STATE_RXFIFO_OVERFLOW)) {
serialSendln("RX Underflowed; Strobing SFRX...");
strobe(SFRX);
}
strobe(SNOP);
serialSend("TX FIFO_BYTES_AVAILABLE: ");
snprintf(buffer, sizeof(buffer), "0x%x", statusByte & FIFO_BYTES_AVAILABLE);
serialSendln(buffer);

vTaskDelay(pdMS_TO_TICKS(5000)); // do we need this?
strobe(SNOP | READ_BIT);
serialSend("RX FIFO_BYTES_AVAILABLE: ");
snprintf(buffer, sizeof(buffer), "0x%x", statusByte & FIFO_BYTES_AVAILABLE);
serialSendln(buffer);
/**
* Strobe a NOP to ensure last operation was a write.
* Then statusByte will be primed with FIFO_BYTES_AVAILABLE for TX FIFO.
*/
strobe(SNOP);
if (writeToTxFIFO(test, packetLen) == 1) {
snprintf(buffer, sizeof(buffer), "%d Bytes Radio TX FIFO written", packetLen);
serialSendln(buffer);
} else {
snprintf(buffer, sizeof(buffer), "Radio did not write");
serialSendln(buffer);
}
txbytes = readRegister(TXBYTES);
tx_underflowed = txbytes & TXFIFO_UNDERFLOW;
tx_numbytes = txbytes & NUM_TXBYTES;
snprintf(buffer, sizeof(buffer), "AFTER: tx_underflowed:%s tx_numbytes:%d", tx_underflowed ? "yes" : "no", tx_numbytes);
serialSendln(buffer);

strobe(SRX);
//strobe(STX);
serialSendln("STX strobed...");
strobe(SNOP);
printStatusByte();

//TODO: use timer and return timeout error if radio never returns to IDLE, this should be done for most state transitions

uint8 rxbytes = readRegister(RXBYTES);
uint8 rx_overflowed = rxbytes & RXFIFO_OVERFLOW;
uint8 rx_numbytes = rxbytes & NUM_RXBYTES;
if(rxbytes != 0){
snprintf(buffer, sizeof(buffer), "rx_overflowed:%s rx_numbytes:%d", rx_overflowed ? "yes" : "no", rx_numbytes);
serialSendln(buffer);
if(readFromRxFIFO(test, rxbytes) == 1) {
snprintf(buffer, sizeof(buffer), "Read %d bytes from RX FIFO", rxbytes);
serialSendln(buffer);
} else {
serialSendln("Failed to read from RX FIFO");
}
for (i = 0; i < packetLen; i++) {
snprintf(buffer, sizeof(buffer), "RX Byte #%d: %02x", i, test[i]);
serialSendln(buffer);
}
}
}

// TX task
Expand Down Expand Up @@ -381,52 +440,61 @@ static void strobe(uint8 addr) {
serialSendln(buffer);
}

static void printStatusByte() {
char buffer[30];
snprintf(buffer, sizeof(buffer), "StatusByte: 0x%02x\n", statusByte);
serialSend(buffer);
}

/**
* Writes values from src buffer into TX FIFO (section 10.5, page 32).
*
* Assumes last operation was a write (header has R/W bit set to 0); that FIFO_BYTES_AVAILABLE contains number of bytes free in TX FIFO.
* Currently only supports complete writes (when size of data to send is <= to numBytesInFIFO).
* TODO: Support partial writes (write what we can first, eg, what's sent is = numBytesInFIFO, then send the rest of it later).
* Currently only supports complete writes (when size of data to send is <= to numBytesAvailInFIFO).
* TODO: Support partial writes (write what we can first, eg, what's sent is = numBytesAvailInFIFO, then send the rest of it later).
*
* @param src Data buffer to send
* @param size Size of src (number of bytes)
* @return -1 on underflow, 0 on failure (insufficient size), 1 on successful write, 2 on unexpected size
*/
static int writeToTxFIFO(const uint8 *src, uint8 size) {
uint8 numBytesInFIFO = statusByte & FIFO_BYTES_AVAILABLE;
static int writeToTxFIFO(const uint8 *src, uint8 numBytesToWrite) {
uint8 numBytesAvailInFIFO = statusByte & FIFO_BYTES_AVAILABLE;
/**
* numBytesInFIFO is 4 bits; if it is 0xF, then >= 15 bytes are free in TX FIFO (i.e., there could be
* numBytesAvailInFIFO is 4 bits; if it is 0xF, then >= 15 bytes are free in TX FIFO (i.e., there could be
* anywhere from 15-64 bytes free).
* Thus, comparing size to numBytesInFIFO gives a definitive result only if numBytesInFIFO is < 0xF.
* Thus, comparing size to numBytesAvailInFIFO gives a definitive result only if numBytesAvailInFIFO is < 0xF.
* To get the actual full count of free bytes in FIFO, we then read the proper status register.
*/
if (size > numBytesInFIFO) {
if (numBytesInFIFO >= 0xF) {
numBytesInFIFO = readRegister(TXBYTES);
if (numBytesInFIFO & TXFIFO_UNDERFLOW) {
if (numBytesToWrite > numBytesAvailInFIFO) {
if (numBytesAvailInFIFO >= 0xF) {
numBytesAvailInFIFO = readRegister(TXBYTES);
if (numBytesAvailInFIFO & TXFIFO_UNDERFLOW) {
return -1;
}
numBytesInFIFO = numBytesInFIFO & NUM_TXBYTES;
if (size > numBytesInFIFO) {
numBytesAvailInFIFO = 64 - (numBytesAvailInFIFO & NUM_TXBYTES);
/**
* Now numBytesAvailInFIFO is number of bytes currently in RF TX FIFO.
*/
if (numBytesToWrite > numBytesAvailInFIFO) {
return 0;
}
} else {
return 0;
}
}
/*
* TODO: Determine if it's better to rely on our initial local count of FIFO_BYTES_AVAILABLE via numBytesInFIFO,
* TODO: Determine if it's better to rely on our initial local count of FIFO_BYTES_AVAILABLE via numBytesAvailInFIFO,
* or update this continuously with the radio's count of FIFO_BYTES_AVAILABLE via most recent statusByte.
* I.E: What is more robust: to rely on the the SPI link, or this way?
*/
uint8 idx = 0;
while (numBytesInFIFO > 0 && idx < size) {
while (numBytesAvailInFIFO > 0 && idx < numBytesToWrite) {
writeRegister(FIFO_TX, src[idx++]); //FIFO_TX single byte access
/**
* TODO: Opportunity to do a sanity check on the new numBytesInFIFO here with our current numBytesInFIFO.
* uint8 newNumBytesInFIFO = statusByte & FIFO_BYTES_AVAILABLE;
* TODO: Opportunity to do a sanity check on the new numBytesAvailInFIFO here with our current numBytesAvailInFIFO.
* uint8 newnumBytesAvailInFIFO = statusByte & FIFO_BYTES_AVAILABLE;
*/
numBytesInFIFO--;
numBytesAvailInFIFO--;
}
return 1;
}
Expand All @@ -440,17 +508,18 @@ static int writeToTxFIFO(const uint8 *src, uint8 size) {
* @param size Size of dest (number of bytes)
* @return 1 if all bytes in FIFO read successfully, 0 otherwise (partial read, dest is too small to fit the rest, etc)
*/
static int readFromRxFIFO(uint8 *dest, uint8 size) {
uint8 numBytesInFIFO = statusByte & FIFO_BYTES_AVAILABLE;
static int readFromRxFIFO(uint8 *dest, uint8 numBytesToRead) {
//uint8 numBytesAvailInFIFO = statusByte & FIFO_BYTES_AVAILABLE;
uint8 numBytesAvailInFIFO = readRegister(RXBYTES);
uint8 idx = 0;
while (numBytesInFIFO > 0 && idx + 1 <= size) {
while (numBytesAvailInFIFO > 0 && idx < numBytesToRead) {
dest[idx++] = readRegister(FIFO_RX);
numBytesInFIFO--;
numBytesAvailInFIFO--;
}
/**
* If there are no bytes left in the FIFO yet we've managed to read at least one, then all bytes have been read successfully.
*/
return (numBytesInFIFO == 0 && idx >= 1);
return (numBytesAvailInFIFO == 0 && idx >= 1);
}

static void writeAllConfigRegisters(const uint16 config[NUM_CONFIG_REGISTERS]) {
Expand All @@ -475,7 +544,7 @@ static void readAllConfigRegisters() {
}

static uint8 * readAllStatusRegisters() {
static uint8 contents[14];
static uint8 contents[NUM_STATUS_REGISTERS];
contents[0] = readRegister(PARTNUM);
contents[1] = readRegister(VERSION);
contents[2] = readRegister(FREQEST);
Expand Down Expand Up @@ -554,15 +623,11 @@ void gio_notification_RF(gioPORT_t *port, uint32 bit){
xHigherPriorityTaskWoken = pdFALSE;

if(port == GIO_IRQ_PORT && bit == GIO_IRQ_PIN){ // Always need to check which pin actually triggered the interrupt

xSemaphoreGiveFromISR(gioRFSem, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}




BaseType_t initRadio() {
//what task should SPI initialization occure in?
spiDataConfig.CS_HOLD = RF_CONFIG_CS_HOLD;
Expand All @@ -578,9 +643,6 @@ BaseType_t initRadio() {
uint8 *stat = readAllStatusRegisters();
char buffer[30];




strobe(SRES);
strobe(SNOP);

Expand Down

0 comments on commit ed43414

Please sign in to comment.