working version - communication with a single client tested, works

retry
Ondřej Hruška 7 years ago
parent 5f563e9038
commit 99904eec7c
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 3
      Inc/nrf.h
  2. 35
      Src/gex_gateway.c
  3. 2
      Src/gpio.c
  4. 13
      Src/main.c
  5. 127
      Src/nrf.c
  6. 2
      Src/spi.c

@ -21,6 +21,9 @@
#include "main.h" #include "main.h"
#define dbg_nrf(...) do{}while(0)
//#define dbg_nrf(...) dbg(##__VA_ARGS__)
// Initialize SPI and the Nordic // Initialize SPI and the Nordic
/** /**

@ -86,10 +86,10 @@ void handle_txframe_chunk(const uint8_t *buffer, uint16_t size)
ck = ~ck; ck = ~ck;
if (ck != txmsg_cksum) { if (ck != txmsg_cksum) {
dbg("Checksum mismatch!"); dbg("Checksum from usb master mismatch!");
} }
else { else {
dbg("Verified, sending a %d B frame to slave.", (int) txmsg_len); dbg_nrf("Verified, sending a %d B frame to slave.", (int) txmsg_len);
uint8_t pipe = NRF_Addr2PipeNum(txmsg_addr); uint8_t pipe = NRF_Addr2PipeNum(txmsg_addr);
if (pipe == 0xFF) { if (pipe == 0xFF) {
@ -102,10 +102,13 @@ void handle_txframe_chunk(const uint8_t *buffer, uint16_t size)
remain -= chunk; remain -= chunk;
if (!suc) { if (!suc) {
dbg("Sending failed."); // (even with retransmission) dbg("Sending failed, discard rest");
break; // skip rest of the frame break; // skip rest of the frame
} }
} }
if (remain == 0) {
dbg_nrf("Sending completed. Is Rx ready? %d", (int)NRF_IsRxPacket());
}
} }
} }
@ -152,7 +155,7 @@ void gw_handle_usb_out(uint8_t *buffer)
} }
start_slave_cmd(slave_addr, frame_len, cksum); start_slave_cmd(slave_addr, frame_len, cksum);
dbg("Collecting frame for slave %02x: %d bytes", (int)slave_addr, (int)frame_len); dbg_nrf("Collecting frame for slave %02x: %d bytes", (int)slave_addr, (int)frame_len);
cmd_state = CMD_STATE_TXMSG; cmd_state = CMD_STATE_TXMSG;
// handle the rest as payload // handle the rest as payload
@ -189,14 +192,14 @@ void handle_cmd_addnodes(PayloadParser *pp)
if (!suc) { if (!suc) {
dbg("Failed to add node."); dbg("Failed to add node.");
} else { } else {
dbg("Bound node %02x to pipe %d", node, pipenum); dbg_nrf("Bound node %02x to pipe %d", node, pipenum);
} }
} }
} }
void respond_gw_id(void) void respond_gw_id(void)
{ {
dbg("> respond_gw_id"); dbg_nrf("> respond_gw_id");
struct msg_network_id m = { struct msg_network_id m = {
.msg_type = MSG_TYPE_NETWORK_ID, .msg_type = MSG_TYPE_NETWORK_ID,
.bytes = { .bytes = {
@ -234,47 +237,35 @@ static void compute_network_id(void)
pb = pb_start(gex_network, 4, NULL); pb = pb_start(gex_network, 4, NULL);
pb_u32(&pb, ck); pb_u32(&pb, ck);
dbg("Dongle network ID: %02X-%02X-%02X-%02X", dbg("Gateway network ID: %02X-%02X-%02X-%02X",
gex_network[0], gex_network[1], gex_network[2], gex_network[3]); gex_network[0], gex_network[1], gex_network[2], gex_network[3]);
} }
void gw_setup_radio(void) void gw_setup_radio(void)
{ {
bool suc;
dbg("Init NRF"); dbg("Init NRF");
NRF_Init(NRF_SPEED_2M); NRF_Init(NRF_SPEED_2M);
compute_network_id(); compute_network_id();
NRF_SetBaseAddress(gex_network); NRF_SetBaseAddress(gex_network);
// TODO by config
uint8_t pipenum;
suc = NRF_AddPipe(0x01, &pipenum);
dbg("Pipe added? %d, num %d", (int)suc, (int)pipenum);
NRF_ModeRX(); // base state is RX NRF_ModeRX(); // base state is RX
// dbg("Send a packet");
//
// suc = NRF_SendPacket(pipenum, (uint8_t *) "AHOJ", 5);
// dbg("Suc? %d", (int)suc);
} }
void EXTI2_IRQHandler(void) void EXTI2_IRQHandler(void)
{ {
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_2);
struct msg_data m; struct msg_data m;
m.msg_type = MSG_TYPE_DATA; m.msg_type = MSG_TYPE_DATA;
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_2);
uint8_t pipenum; uint8_t pipenum;
m.length = NRF_ReceivePacket(m.data, &pipenum); m.length = NRF_ReceivePacket(m.data, &pipenum);
if (m.length == 0) { if (m.length == 0) {
dbg("IRQ but no msg!"); dbg("IRQ but no msg!");
} }
else { else {
dbg("Msg RXd from nordic!"); dbg_nrf("Msg RXd from nordic!");
m.dev_addr = NRF_PipeNum2Addr(pipenum); m.dev_addr = NRF_PipeNum2Addr(pipenum);

@ -106,7 +106,7 @@ void MX_GPIO_Init(void)
EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_2; EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_2;
EXTI_InitStruct.LineCommand = ENABLE; EXTI_InitStruct.LineCommand = ENABLE;
EXTI_InitStruct.Mode = LL_EXTI_MODE_IT; EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_RISING; EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_FALLING;
LL_EXTI_Init(&EXTI_InitStruct); LL_EXTI_Init(&EXTI_InitStruct);
NVIC_EnableIRQ(EXTI2_IRQn); NVIC_EnableIRQ(EXTI2_IRQn);

@ -82,6 +82,8 @@ void SystemClock_Config(void);
/* USER CODE END 0 */ /* USER CODE END 0 */
extern void EXTI2_IRQHandler(void);
/** /**
* @brief The application entry point. * @brief The application entry point.
* *
@ -130,16 +132,19 @@ int main(void)
/* Infinite loop */ /* Infinite loop */
/* USER CODE BEGIN WHILE */ /* USER CODE BEGIN WHILE */
int cnt = 0; int cnt = 0;
uint8_t buff[MQ_SLOT_LEN];
while (1) { while (1) {
if (cnt++ > 500000) { if (cnt++ > 500000) {
LL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); LL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
cnt = 0; cnt = 0;
} }
uint8_t buff[MQ_SLOT_LEN]; if (mq_can_read(&usb_inq)) {
if (!usb_tx_busy && mq_can_read(&usb_inq)) { if (!usb_tx_busy) {
mq_read(&usb_inq, buff); mq_read(&usb_inq, buff);
CDC_Transmit_FS(buff, MQ_SLOT_LEN); CDC_Transmit_FS(buff, MQ_SLOT_LEN);
}
} }
} }
/* USER CODE END 3 */ /* USER CODE END 3 */

@ -139,9 +139,6 @@ static uint8_t spi(uint8_t tx) {
RD_CONFIG_EN_CRC | \ RD_CONFIG_EN_CRC | \
RD_CONFIG_CRCO) RD_CONFIG_CRCO)
#define CEHIGH CE(1)
#define CELOW CE(0)
static inline uint8_t CS(uint8_t hl) static inline uint8_t CS(uint8_t hl)
{ {
if (hl == 1) { if (hl == 1) {
@ -169,7 +166,19 @@ static uint8_t NRF_WriteRegister(uint8_t reg, uint8_t value)
status = spi(CMD_WRITE_REG | reg); status = spi(CMD_WRITE_REG | reg);
spi(value); spi(value);
} }
dbg("Wr[0x%02x] := 0x%02x", (int)reg, (int) value); dbg_nrf("Wr[0x%02x] := 0x%02x", (int)reg, (int) value);
uint8_t reg_val = 0;
CHIPSELECT {
spi(CMD_READ_REG | reg);
reg_val = spi(0);
}
dbg_nrf(" verify 0x%02x", (int)reg_val);
if (reg_val != value)
dbg_nrf(" !!!");
else
dbg_nrf(" OK");
return status; return status;
} }
@ -180,7 +189,7 @@ static uint8_t NRF_ReadRegister(uint8_t reg)
spi(CMD_READ_REG | reg); spi(CMD_READ_REG | reg);
reg_val = spi(0); reg_val = spi(0);
} }
dbg("Rd[0x%02x] = 0x%02x", (int)reg, (int) reg_val); dbg_nrf("Rd[0x%02x] = 0x%02x", (int)reg, (int) reg_val);
return reg_val; return reg_val;
} }
@ -226,7 +235,7 @@ void NRF_SetBaseAddress(const uint8_t *Bytes4)
void NRF_SetRxAddress(uint8_t pipenum, uint8_t AddrByte) void NRF_SetRxAddress(uint8_t pipenum, uint8_t AddrByte)
{ {
if (pipenum > 5) { if (pipenum > 5) {
dbg("!! bad pipe %d", pipenum); dbg_nrf("!! bad pipe %d", pipenum);
return; return;
} }
@ -234,13 +243,13 @@ void NRF_SetRxAddress(uint8_t pipenum, uint8_t AddrByte)
nrf_pipe_addr[pipenum] = AddrByte; nrf_pipe_addr[pipenum] = AddrByte;
dbg("Set Rx addr (pipe %d) = 0x%02x", (int)pipenum, AddrByte); dbg_nrf("Set Rx addr (pipe %d) = 0x%02x", (int)pipenum, AddrByte);
if (pipenum == 0) { if (pipenum == 0) {
dbg("W ADDR_PA0: %02X-%02X-%02X-%02X-%02X", nrf_base_address[0], nrf_base_address[1], nrf_base_address[2], nrf_base_address[3], nrf_base_address[4]); dbg_nrf("W ADDR_PA0: %02X-%02X-%02X-%02X-%02X", nrf_base_address[0], nrf_base_address[1], nrf_base_address[2], nrf_base_address[3], nrf_base_address[4]);
NRF_WriteBuffer(RG_RX_ADDR_P0, nrf_base_address, 5); NRF_WriteBuffer(RG_RX_ADDR_P0, nrf_base_address, 5);
} }
else if (pipenum == 1) { else if (pipenum == 1) {
dbg("W ADDR_PA1: %02X-%02X-%02X-%02X-%02X", nrf_base_address[0], nrf_base_address[1], nrf_base_address[2], nrf_base_address[3], nrf_base_address[4]); dbg_nrf("W ADDR_PA1: %02X-%02X-%02X-%02X-%02X", nrf_base_address[0], nrf_base_address[1], nrf_base_address[2], nrf_base_address[3], nrf_base_address[4]);
NRF_WriteBuffer(RG_RX_ADDR_P1, nrf_base_address, 5); NRF_WriteBuffer(RG_RX_ADDR_P1, nrf_base_address, 5);
} }
else { else {
@ -278,6 +287,7 @@ uint8_t NRF_Addr2PipeNum(uint8_t addr)
void NRF_EnablePipe(uint8_t pipenum) void NRF_EnablePipe(uint8_t pipenum)
{ {
dbg_nrf("Enable pipe num %d", (int)pipenum);
uint8_t enabled = NRF_ReadRegister(RG_EN_RXADDR); uint8_t enabled = NRF_ReadRegister(RG_EN_RXADDR);
enabled |= 1 << pipenum; enabled |= 1 << pipenum;
NRF_WriteRegister(RG_EN_RXADDR, enabled); NRF_WriteRegister(RG_EN_RXADDR, enabled);
@ -298,34 +308,39 @@ static void NRF_SetTxAddress(uint8_t SendTo)
{ {
nrf_base_address[4] = SendTo; nrf_base_address[4] = SendTo;
dbg("W Tx_ADDR + Rx0: %02X-%02X-%02X-%02X-%02X", nrf_base_address[0], nrf_base_address[1], nrf_base_address[2], nrf_base_address[3], nrf_base_address[4]); dbg_nrf("W Tx_ADDR + Rx0: %02X-%02X-%02X-%02X-%02X",
nrf_base_address[0], nrf_base_address[1], nrf_base_address[2], nrf_base_address[3], nrf_base_address[4]);
NRF_WriteBuffer(RG_TX_ADDR, nrf_base_address, 5); NRF_WriteBuffer(RG_TX_ADDR, nrf_base_address, 5);
NRF_WriteBuffer(RG_RX_ADDR_P0, nrf_base_address, 5); // the ACK will come to pipe 0 NRF_WriteBuffer(RG_RX_ADDR_P0, nrf_base_address, 5); // the ACK will come to pipe 0
} }
void NRF_PowerDown(void) void NRF_PowerDown(void)
{ {
dbg("PDn"); dbg_nrf("PDn");
CELOW; CE(0);
NRF_WriteRegister(RG_CONFIG, ModeBits); NRF_WriteRegister(RG_CONFIG, ModeBits);
} }
void NRF_ModeTX(void) void NRF_ModeTX(void)
{ {
dbg("Tx Mode"); dbg_nrf("Tx Mode");
CELOW; CE(0);
uint8_t m = NRF_ReadRegister(RG_CONFIG); uint8_t m = NRF_ReadRegister(RG_CONFIG);
NRF_WriteRegister(RG_CONFIG, ModeBits | RD_CONFIG_PWR_UP); NRF_WriteRegister(RG_CONFIG, ModeBits | RD_CONFIG_PWR_UP);
if ((m & RD_CONFIG_PWR_UP) == 0) LL_mDelay(5); if ((m & RD_CONFIG_PWR_UP) == 0) {
// switching on
LL_mDelay(5);
}
} }
void NRF_ModeRX(void) void NRF_ModeRX(void)
{ {
dbg("Rx Mode"); dbg_nrf("Rx Mode");
NRF_WriteRegister(RG_CONFIG, ModeBits | RD_CONFIG_PWR_UP | RD_CONFIG_PRIM_RX); NRF_WriteRegister(RG_CONFIG, ModeBits | RD_CONFIG_PWR_UP | RD_CONFIG_PRIM_RX);
NRF_SetRxAddress(0, nrf_pipe_addr[0]); // set the P0 address - it was changed during Rx for ACK reception NRF_SetRxAddress(0, nrf_pipe_addr[0]); // set the P0 address - it was changed during Rx for ACK reception
CEHIGH; CE(1);
//if ((m&2)==0) LL_mDelay()(5); You don't need to wait. Just nothing will come for 5ms or more //if ((m&2)==0) LL_mDelay()(5); You don't need to wait. Just nothing will come for 5ms or more
} }
@ -363,7 +378,9 @@ uint8_t NRF_ReceivePacket(uint8_t *Packet, uint8_t *PipeNum)
uint8_t pw = 0, status; uint8_t pw = 0, status;
if (!NRF_IsRxPacket()) return 0; if (!NRF_IsRxPacket()) return 0;
CELOW; const uint8_t orig_conf = NRF_ReadRegister(RG_CONFIG);
CE(0); // quit Rx mode - go idle
CHIPSELECT { CHIPSELECT {
status = spi(CMD_RD_RX_PL_WIDTH); status = spi(CMD_RD_RX_PL_WIDTH);
pw = spi(0); pw = spi(0);
@ -373,19 +390,25 @@ uint8_t NRF_ReceivePacket(uint8_t *Packet, uint8_t *PipeNum)
CHIPSELECT { CHIPSELECT {
spi(CMD_FLUSH_RX); spi(CMD_FLUSH_RX);
} }
NRF_WriteRegister(RG_STATUS, RD_STATUS_RX_DR); pw = 0;
return 0; } else {
// Read the reception pipe number
*PipeNum = ((status & RD_STATUS_RX_PNO) >> 1);
CHIPSELECT {
spi(CMD_RD_RX_PLD);
for (uint8_t i = 0; i < pw; i++) Packet[i] = spi(0);
}
} }
NRF_WriteRegister(RG_STATUS, RD_STATUS_RX_DR); // Clear the RX_DR interrupt
// Read the reception pipe number if ((orig_conf & RD_CONFIG_PWR_UP) == 0) {
*PipeNum = (status & RD_STATUS_RX_PNO) >> 1; dbg_nrf("going back PwrDn");
NRF_PowerDown();
CHIPSELECT { }
spi(CMD_RD_RX_PLD); else if ((orig_conf & RD_CONFIG_PRIM_RX) == RD_CONFIG_PRIM_RX) {
for (uint8_t i = 0; i < pw; i++) Packet[i] = spi(0); dbg_nrf("going back PwrUp+Rx");
NRF_ModeRX();
} }
NRF_WriteRegister(RG_STATUS, RD_STATUS_RX_DR); // Clear the RX_DR interrupt
CEHIGH;
return pw; return pw;
} }
@ -398,14 +421,14 @@ bool NRF_IsRxPacket(void)
bool NRF_SendPacket(uint8_t PipeNum, const uint8_t *Packet, uint8_t Length) bool NRF_SendPacket(uint8_t PipeNum, const uint8_t *Packet, uint8_t Length)
{ {
if (!nrf_pipe_enabled[PipeNum]) { if (!nrf_pipe_enabled[PipeNum]) {
dbg("!! Pipe %d not enabled", PipeNum); dbg_nrf("!! Pipe %d not enabled", PipeNum);
return 0; return 0;
} }
const uint8_t orig_conf = NRF_ReadRegister(RG_CONFIG); const uint8_t orig_conf = NRF_ReadRegister(RG_CONFIG);
CELOW; CE(0);
NRF_ModeTX(); // Make sure in TX mode NRF_ModeTX(); // Make sure in TX mode
NRF_SetTxAddress(nrf_pipe_addr[PipeNum]); NRF_SetTxAddress(nrf_pipe_addr[PipeNum]); // this sets the Tx addr and also pipe 0 addr for ACK
CHIPSELECT { CHIPSELECT {
spi(CMD_FLUSH_TX); spi(CMD_FLUSH_TX);
@ -416,25 +439,27 @@ bool NRF_SendPacket(uint8_t PipeNum, const uint8_t *Packet, uint8_t Length)
for (uint8_t i = 0; i < Length; i++) spi(Packet[i]); for (uint8_t i = 0; i < Length; i++) spi(Packet[i]);
}; };
CEHIGH; // CE pulse
_delay_us(15); // At least 10 us CE(1);
CELOW; _delay_us(20); // At least 10 us
CE(0);
uint8_t st = 0; uint8_t st = 0;
while ((st & (RD_STATUS_MAX_RT|RD_STATUS_TX_DS)) == 0) { while ((st & (RD_STATUS_MAX_RT|RD_STATUS_TX_DS)) == 0) {
st = NRF_ReadStatus(); // Packet acked or timed out st = NRF_ReadStatus(); // Packet acked or timed out
} }
dbg("Send status: MAX_RT %d, SENT %d", (st&RD_STATUS_MAX_RT) != 0, (st&RD_STATUS_TX_DS) != 0); dbg_nrf("Send status: 0x%02x - MAX_RT %d, SENT %d", (int)st,
(st&RD_STATUS_MAX_RT) != 0, (st&RD_STATUS_TX_DS) != 0);
NRF_WriteRegister(RG_STATUS, st & (RD_STATUS_MAX_RT|RD_STATUS_TX_DS)); // Clear the bit NRF_WriteRegister(RG_STATUS, st & (RD_STATUS_MAX_RT|RD_STATUS_TX_DS)); // Clear the bit
if ((orig_conf & RD_CONFIG_PWR_UP) == 0) { if ((orig_conf & RD_CONFIG_PWR_UP) == 0) {
dbg("going back PwrDn"); dbg_nrf("going back PwrDn");
NRF_PowerDown(); NRF_PowerDown();
} }
else if ((orig_conf & RD_CONFIG_PRIM_RX) == RD_CONFIG_PRIM_RX) { else if ((orig_conf & RD_CONFIG_PRIM_RX) == RD_CONFIG_PRIM_RX) {
dbg("going back PwrUp+Rx"); dbg_nrf("going back PwrUp+Rx");
NRF_ModeRX(); NRF_ModeRX();
} }
@ -455,27 +480,35 @@ void NRF_Init(uint8_t pSpeed)
{ {
// Set the required output pins // Set the required output pins
NSS(1); NSS(1);
CELOW; CE(0);
LL_mDelay(200); LL_mDelay(200);
for (int i = 0; i < 6; i++) {
nrf_pipe_addr[i] = 0;
nrf_pipe_enabled[i] = 0;
}
// clear flags etc
NRF_PowerDown();
CHIPSELECT { spi(CMD_FLUSH_RX); }
CHIPSELECT { spi(CMD_FLUSH_TX); }
NRF_WriteRegister(RG_STATUS, 0x70);
NRF_WriteRegister(RG_CONFIG, ModeBits); NRF_WriteRegister(RG_CONFIG, ModeBits);
NRF_WriteRegister(RG_SETUP_AW, 0b11); // 5 byte addresses NRF_WriteRegister(RG_SETUP_AW, 0b11); // 5 byte addresses
// default NRF_WriteRegister(RG_EN_RXADDR, 0x00); // disable all
// NRF_EnablePipe(0);
NRF_WriteRegister(RG_SETUP_RETR, 0x18); // 8 retries NRF_WriteRegister(RG_SETUP_RETR, 0x18); // 8 retries, 500 ms
NRF_WriteRegister(RG_RF_CH, 2); // channel 2 NO HIGHER THAN 83 in USA! NRF_WriteRegister(RG_RF_CH, 7); // channel 2 NO HIGHER THAN 83 in USA!
NRF_WriteRegister(RG_RF_SETUP, pSpeed); NRF_WriteRegister(RG_RF_SETUP, pSpeed);
NRF_WriteRegister(RG_DYNPD, 0b111111); // Dynamic packet length NRF_WriteRegister(RG_DYNPD, 0b111111); // Dynamic packet length
NRF_WriteRegister(RG_FEATURE, 0b100); // Enable dynamic payload, and no payload in the ack. NRF_WriteRegister(RG_FEATURE, 0b100); // Enable dynamic payload, and no payload in the ack.
for (int i = 0; i < 6; i++) { // for (int i = 0; i < 6; i++) {
NRF_WriteRegister(RG_RX_PW_P0+i, 32); // Receive 32 byte packets - XXX this is probably not needed with dynamic length // NRF_WriteRegister(RG_RX_PW_P0+i, 32); // Receive 32 byte packets - XXX this is probably not needed with dynamic length
} // }
//NRFModePowerDown(); // Already in power down mode, dummy
} }

@ -119,7 +119,7 @@ void MX_SPI1_Init(void)
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER; SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT; SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW; SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE; SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8; SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8;
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;

Loading…
Cancel
Save