|
|
@ -13,6 +13,23 @@ |
|
|
|
#include "crc32.h" |
|
|
|
#include "crc32.h" |
|
|
|
#include "payload_builder.h" |
|
|
|
#include "payload_builder.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enum MsgTypes { |
|
|
|
|
|
|
|
MSG_TYPE_NETWORK_ID = 1, |
|
|
|
|
|
|
|
MSG_TYPE_DATA = 2, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct msg_network_id { |
|
|
|
|
|
|
|
uint8_t msg_type; |
|
|
|
|
|
|
|
uint8_t bytes[4]; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct msg_data { |
|
|
|
|
|
|
|
uint8_t msg_type; |
|
|
|
|
|
|
|
uint8_t dev_addr; |
|
|
|
|
|
|
|
uint8_t length; |
|
|
|
|
|
|
|
uint8_t data[32]; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static uint8_t gex_network[4]; |
|
|
|
static uint8_t gex_network[4]; |
|
|
|
|
|
|
|
|
|
|
|
// USB RX
|
|
|
|
// USB RX
|
|
|
@ -36,13 +53,13 @@ static uint8_t txmsg_cksum = 0; |
|
|
|
enum GW_CMD { |
|
|
|
enum GW_CMD { |
|
|
|
CMD_GET_ID = 'i', // 105 - get network ID
|
|
|
|
CMD_GET_ID = 'i', // 105 - get network ID
|
|
|
|
CMD_RESET = 'r', // reset the radio and network
|
|
|
|
CMD_RESET = 'r', // reset the radio and network
|
|
|
|
CMD_ADD_NODE = 'n', // add a node by address byte
|
|
|
|
CMD_ADD_NODES = 'n', // add a node by address byte
|
|
|
|
CMD_TXMSG = 'm', // 109 - send a message
|
|
|
|
CMD_TXMSG = 'm', // 109 - send a message
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
void respond_gw_id(void); |
|
|
|
void respond_gw_id(void); |
|
|
|
|
|
|
|
|
|
|
|
void handle_cmd_addnode(PayloadParser *pp); |
|
|
|
void handle_cmd_addnodes(PayloadParser *pp); |
|
|
|
|
|
|
|
|
|
|
|
void handle_cmd_reset(void); |
|
|
|
void handle_cmd_reset(void); |
|
|
|
|
|
|
|
|
|
|
@ -54,10 +71,52 @@ void start_slave_cmd(uint8_t slave_addr, uint16_t frame_len, uint8_t cksum) |
|
|
|
txmsg_cksum = cksum; |
|
|
|
txmsg_cksum = cksum; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void handle_txframe_chunk(const uint8_t *buffer, uint16_t size) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
uint32_t wanted = MIN(txmsg_len - txmsg_collected, size); |
|
|
|
|
|
|
|
memcpy(&txmsg_payload[txmsg_collected], buffer, wanted); |
|
|
|
|
|
|
|
txmsg_collected += wanted; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (wanted < size) { |
|
|
|
|
|
|
|
// this was the end - simple checksum to verify it's a valid frame
|
|
|
|
|
|
|
|
uint8_t ck = 0; |
|
|
|
|
|
|
|
for (int i = 0; i < txmsg_len; i++) { |
|
|
|
|
|
|
|
ck ^= txmsg_payload[i]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ck = ~ck; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ck != txmsg_cksum) { |
|
|
|
|
|
|
|
dbg("Checksum mismatch!"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
dbg("Verified, sending a %d B frame to slave.", (int) txmsg_len); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t pipe = NRF_Addr2PipeNum(txmsg_addr); |
|
|
|
|
|
|
|
if (pipe == 0xFF) { |
|
|
|
|
|
|
|
dbg("Bad slave num!"); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
uint32_t remain = txmsg_len; |
|
|
|
|
|
|
|
for (int i = 0; i <= txmsg_len/32; i++) { |
|
|
|
|
|
|
|
uint8_t chunk = (uint8_t) MIN(remain, 32); |
|
|
|
|
|
|
|
bool suc = NRF_SendPacket(pipe, &txmsg_payload[i*32], chunk); |
|
|
|
|
|
|
|
remain -= chunk; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!suc) { |
|
|
|
|
|
|
|
dbg("Sending failed."); // (even with retransmission)
|
|
|
|
|
|
|
|
break; // skip rest of the frame
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd_state = CMD_STATE_IDLE; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void gw_handle_usb_out(uint8_t *buffer) |
|
|
|
void gw_handle_usb_out(uint8_t *buffer) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (cmd_state == CMD_STATE_IDLE) { |
|
|
|
if (cmd_state == CMD_STATE_IDLE) { |
|
|
|
PayloadParser pp = pp_start(buffer, MQ_SLOT_LEN, NULL); |
|
|
|
PayloadParser pp = pp_start(buffer, 64, NULL); |
|
|
|
|
|
|
|
|
|
|
|
// handle binary commands for the gateway
|
|
|
|
// handle binary commands for the gateway
|
|
|
|
|
|
|
|
|
|
|
@ -75,11 +134,14 @@ void gw_handle_usb_out(uint8_t *buffer) |
|
|
|
handle_cmd_reset(); |
|
|
|
handle_cmd_reset(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case CMD_ADD_NODE: |
|
|
|
case CMD_ADD_NODES: |
|
|
|
handle_cmd_addnode(&pp); |
|
|
|
// payload is: u8-count, u8[] node addresses
|
|
|
|
|
|
|
|
handle_cmd_addnodes(&pp); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case CMD_TXMSG:; |
|
|
|
case CMD_TXMSG:; |
|
|
|
|
|
|
|
// u8-slave-addr, u16-len, u8-checksum
|
|
|
|
|
|
|
|
// the message is sent in the following frames.
|
|
|
|
uint8_t slave_addr = pp_u8(&pp); |
|
|
|
uint8_t slave_addr = pp_u8(&pp); |
|
|
|
uint16_t frame_len = pp_u16(&pp); |
|
|
|
uint16_t frame_len = pp_u16(&pp); |
|
|
|
uint8_t cksum = pp_u8(&pp); |
|
|
|
uint8_t cksum = pp_u8(&pp); |
|
|
@ -92,6 +154,11 @@ 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("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
|
|
|
|
|
|
|
|
uint32_t len; |
|
|
|
|
|
|
|
const uint8_t *tail = pp_tail(&pp, &len); |
|
|
|
|
|
|
|
handle_txframe_chunk(tail, (uint16_t) len); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
default: |
|
|
@ -103,65 +170,47 @@ void gw_handle_usb_out(uint8_t *buffer) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else if (cmd_state == CMD_STATE_TXMSG) { |
|
|
|
else if (cmd_state == CMD_STATE_TXMSG) { |
|
|
|
uint32_t wanted = MIN(txmsg_len - txmsg_collected, MQ_SLOT_LEN); |
|
|
|
handle_txframe_chunk(buffer, 64); |
|
|
|
memcpy(&txmsg_payload[txmsg_collected], buffer, wanted); |
|
|
|
|
|
|
|
txmsg_collected += wanted; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (wanted < MQ_SLOT_LEN) { |
|
|
|
|
|
|
|
// this was the end - simple checksum to verify it's a valid frame
|
|
|
|
|
|
|
|
uint8_t ck = 0; |
|
|
|
|
|
|
|
for (int i = 0; i < txmsg_len; i++) { |
|
|
|
|
|
|
|
ck ^= txmsg_payload[i]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ck = ~ck; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ck != txmsg_cksum) { |
|
|
|
|
|
|
|
dbg("Checksum mismatch!"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
dbg("Verified, sending a %d B frame to slave.", (int) txmsg_len); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t pipe = NRF_Addr2PipeNum(txmsg_addr); |
|
|
|
|
|
|
|
if (pipe == 0xFF) { |
|
|
|
|
|
|
|
dbg("Bad slave num!"); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
uint32_t remain = txmsg_len; |
|
|
|
|
|
|
|
for (int i = 0; i <= txmsg_len/32; i++) { |
|
|
|
|
|
|
|
uint8_t chunk = (uint8_t) MIN(remain, 32); |
|
|
|
|
|
|
|
bool suc = NRF_SendPacket(pipe, &txmsg_payload[i*32], chunk); |
|
|
|
|
|
|
|
remain -= chunk; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!suc) { |
|
|
|
|
|
|
|
dbg("Sending failed."); // (even with retransmission)
|
|
|
|
|
|
|
|
break; // skip rest of the frame
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd_state = CMD_STATE_IDLE; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void handle_cmd_reset(void) |
|
|
|
void handle_cmd_reset(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
NRF_Reset(); |
|
|
|
NRF_ResetPipes(); |
|
|
|
// TODO also clear queues?
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void handle_cmd_addnode(PayloadParser *pp) |
|
|
|
void handle_cmd_addnodes(PayloadParser *pp) |
|
|
|
{ |
|
|
|
{ |
|
|
|
uint8_t node = pp_u8(pp); |
|
|
|
uint8_t count = pp_u8(pp); |
|
|
|
uint8_t pipenum; |
|
|
|
for(int i = 0; i < count; i++) { |
|
|
|
bool suc = NRF_AddPipe(node, &pipenum); |
|
|
|
uint8_t node = pp_u8(pp); |
|
|
|
if (!suc) dbg("Failed to add node."); |
|
|
|
uint8_t pipenum; |
|
|
|
// TODO response
|
|
|
|
bool suc = NRF_AddPipe(node, &pipenum); |
|
|
|
|
|
|
|
if (!suc) { |
|
|
|
|
|
|
|
dbg("Failed to add node."); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
dbg("Bound node %02x to pipe %d", node, pipenum); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void respond_gw_id(void) |
|
|
|
void respond_gw_id(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// TODO implement (after response system is added)
|
|
|
|
dbg("> respond_gw_id"); |
|
|
|
|
|
|
|
struct msg_network_id m = { |
|
|
|
|
|
|
|
.msg_type = MSG_TYPE_NETWORK_ID, |
|
|
|
|
|
|
|
.bytes = { |
|
|
|
|
|
|
|
gex_network[0], |
|
|
|
|
|
|
|
gex_network[1], |
|
|
|
|
|
|
|
gex_network[2], |
|
|
|
|
|
|
|
gex_network[3], |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool suc = mq_post(&usb_inq, (uint8_t *) &m, sizeof(m)); |
|
|
|
|
|
|
|
if (!suc) { |
|
|
|
|
|
|
|
dbg("IN que overflow!!"); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -206,8 +255,32 @@ void gw_setup_radio(void) |
|
|
|
|
|
|
|
|
|
|
|
NRF_ModeRX(); // base state is RX
|
|
|
|
NRF_ModeRX(); // base state is RX
|
|
|
|
|
|
|
|
|
|
|
|
dbg("Send a packet"); |
|
|
|
// dbg("Send a packet");
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// suc = NRF_SendPacket(pipenum, (uint8_t *) "AHOJ", 5);
|
|
|
|
|
|
|
|
// dbg("Suc? %d", (int)suc);
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EXTI2_IRQHandler(void) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct msg_data m; |
|
|
|
|
|
|
|
m.msg_type = MSG_TYPE_DATA; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_2); |
|
|
|
|
|
|
|
|
|
|
|
suc = NRF_SendPacket(pipenum, (uint8_t *) "AHOJ", 5); |
|
|
|
uint8_t pipenum; |
|
|
|
dbg("Suc? %d", (int)suc); |
|
|
|
m.length = NRF_ReceivePacket(m.data, &pipenum); |
|
|
|
|
|
|
|
if (m.length == 0) { |
|
|
|
|
|
|
|
dbg("IRQ but no msg!"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
dbg("Msg RXd from nordic!"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.dev_addr = NRF_PipeNum2Addr(pipenum); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool suc = mq_post(&usb_inq, (uint8_t *) &m, sizeof(m)); |
|
|
|
|
|
|
|
if (!suc) { |
|
|
|
|
|
|
|
dbg("IN que overflow!!"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|