2016-10-27 18:28:01 +02:00
|
|
|
#include "sss7.h"
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
2016-11-30 22:47:26 +01:00
|
|
|
sss7_shared_modfier enum sss7State sss7_state;
|
2016-10-27 18:28:01 +02:00
|
|
|
|
2016-11-29 19:18:42 +01:00
|
|
|
uint8_t sss7_rx_buffer[SSS7_RX_BUFFER_SIZE][SSS7_PAYLOAD_SIZE];
|
|
|
|
uint8_t sss7_rx_buffer_write;
|
|
|
|
uint8_t sss7_rx_buffer_read;
|
2016-10-27 18:28:01 +02:00
|
|
|
uint8_t sss7_rx_pos;
|
|
|
|
|
|
|
|
uint8_t sss7_tx_buffer[SSS7_PAYLOAD_SIZE];
|
|
|
|
uint8_t sss7_tx_pos;
|
|
|
|
uint8_t sss7_tx_crc;
|
2016-11-30 22:47:26 +01:00
|
|
|
sss7_shared_modfier uint8_t sss7_tx_failed;
|
2016-10-27 23:35:24 +02:00
|
|
|
uint8_t sss7_tx_last_byte;
|
|
|
|
uint8_t sss7_tx_last_ack;
|
2016-10-27 18:28:01 +02:00
|
|
|
|
2016-11-30 22:47:26 +01:00
|
|
|
sss7_shared_modfier uint8_t sss7_timeout_counter;
|
2016-11-21 09:42:22 +01:00
|
|
|
|
2016-11-20 02:24:07 +01:00
|
|
|
|
2016-10-27 23:35:24 +02:00
|
|
|
void sss7_init(void) {
|
2016-10-27 18:28:01 +02:00
|
|
|
sss7_state = SSS7_IDLE;
|
|
|
|
|
|
|
|
sss7_rx_pos = 0;
|
2016-11-29 19:18:42 +01:00
|
|
|
sss7_rx_buffer_read = 0;
|
|
|
|
sss7_rx_buffer_write = 0;
|
2016-10-27 18:28:01 +02:00
|
|
|
|
|
|
|
sss7_tx_pos = 0;
|
|
|
|
sss7_tx_crc = 0;
|
|
|
|
sss7_tx_failed = 0;
|
|
|
|
}
|
|
|
|
|
2016-11-20 02:24:07 +01:00
|
|
|
|
2016-10-27 23:35:24 +02:00
|
|
|
static inline uint8_t sss7_payload_crc(uint8_t buffer[SSS7_PAYLOAD_SIZE]) {
|
2016-10-27 18:28:01 +02:00
|
|
|
uint8_t crc = 0;
|
2016-11-20 02:24:07 +01:00
|
|
|
|
|
|
|
for(uint8_t byte = 0; byte < SSS7_PAYLOAD_SIZE; byte++) {
|
|
|
|
crc = crc ^ buffer[byte];
|
|
|
|
for (uint8_t bit = 0; bit < 8; bit++)
|
|
|
|
{
|
|
|
|
if (crc & 0x01) {
|
|
|
|
crc = (crc >> 1) ^ 0x8C;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
crc >>= 1;
|
|
|
|
}
|
|
|
|
}
|
2016-10-27 18:28:01 +02:00
|
|
|
}
|
2016-11-21 09:42:22 +01:00
|
|
|
|
2016-10-27 18:28:01 +02:00
|
|
|
return crc;
|
|
|
|
}
|
|
|
|
|
2016-11-20 02:24:07 +01:00
|
|
|
|
2016-10-27 23:35:24 +02:00
|
|
|
static inline void sss7_send_byte(uint8_t byte) {
|
|
|
|
sss7_tx_last_ack = 0;
|
|
|
|
sss7_tx_last_byte = byte;
|
2016-11-20 02:24:07 +01:00
|
|
|
uart_put_byte(byte);
|
2016-10-27 23:35:24 +02:00
|
|
|
}
|
|
|
|
|
2016-11-20 02:24:07 +01:00
|
|
|
|
2016-10-27 18:28:01 +02:00
|
|
|
void sss7_send(uint8_t msg[SSS7_PAYLOAD_SIZE]) {
|
|
|
|
// Check that we can send, because we will overwritte the buffer
|
|
|
|
if(sss7_state != SSS7_IDLE) {
|
|
|
|
sss7_tx_failed = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(sss7_tx_buffer, msg, SSS7_PAYLOAD_SIZE);
|
|
|
|
|
|
|
|
sss7_tx_pos = 0;
|
|
|
|
sss7_tx_crc = sss7_payload_crc(sss7_tx_buffer);
|
|
|
|
|
|
|
|
// Commit to send state
|
|
|
|
sss7_state = SSS7_TX_HEADER;
|
2016-10-28 16:13:47 +02:00
|
|
|
sss7_tx_failed = 0;
|
2016-11-21 09:42:22 +01:00
|
|
|
sss7_timeout_counter = 0;
|
2016-10-27 23:35:24 +02:00
|
|
|
sss7_send_byte(SSS7_HEADER[0]);
|
2016-10-27 18:28:01 +02:00
|
|
|
}
|
|
|
|
|
2016-10-27 23:35:24 +02:00
|
|
|
|
2016-11-20 02:24:07 +01:00
|
|
|
void sss7_process_rx(void) {
|
|
|
|
uint8_t byte = uart_get_byte();
|
2016-10-27 18:28:01 +02:00
|
|
|
uint8_t crc = 0;
|
2016-11-29 19:18:42 +01:00
|
|
|
uint8_t next_buffer_write = 0;
|
2016-11-21 09:42:22 +01:00
|
|
|
sss7_timeout_counter = 0;
|
2016-10-27 18:28:01 +02:00
|
|
|
|
2016-12-01 00:14:40 +01:00
|
|
|
switch((int) sss7_state) {
|
2016-10-27 18:28:01 +02:00
|
|
|
case SSS7_IDLE:
|
|
|
|
if(byte == SSS7_HEADER[0]) {
|
|
|
|
sss7_state = SSS7_RX_HEADER;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sss7_state = SSS7_IDLE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SSS7_RX_HEADER:
|
|
|
|
if(byte == SSS7_HEADER[1]) {
|
|
|
|
sss7_state = SSS7_RX_PAYLOAD;
|
|
|
|
sss7_rx_pos = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sss7_state = SSS7_IDLE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SSS7_RX_PAYLOAD:
|
2016-11-29 19:18:42 +01:00
|
|
|
sss7_rx_buffer[sss7_rx_buffer_write][sss7_rx_pos] = byte;
|
2016-10-27 18:28:01 +02:00
|
|
|
sss7_rx_pos++;
|
|
|
|
if(sss7_rx_pos >= SSS7_PAYLOAD_SIZE) {
|
|
|
|
sss7_state = SSS7_RX_CRC;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SSS7_RX_CRC:
|
2016-11-29 19:18:42 +01:00
|
|
|
crc = sss7_payload_crc(sss7_rx_buffer[sss7_rx_buffer_write]);
|
|
|
|
|
|
|
|
next_buffer_write = (sss7_rx_buffer_write + 1) % SSS7_RX_BUFFER_SIZE;
|
|
|
|
// Ensure CRC is okay and we don't overwrite other frames
|
|
|
|
if(byte == crc && next_buffer_write != sss7_rx_buffer_read) {
|
|
|
|
sss7_rx_buffer_write = next_buffer_write;
|
2016-10-27 18:28:01 +02:00
|
|
|
}
|
|
|
|
sss7_state = SSS7_IDLE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// all the TX states
|
|
|
|
default:
|
|
|
|
if(byte != sss7_tx_last_byte) {
|
|
|
|
sss7_state = SSS7_IDLE;
|
|
|
|
sss7_tx_failed = 1;
|
|
|
|
}
|
2016-10-27 23:35:24 +02:00
|
|
|
else {
|
|
|
|
sss7_tx_last_ack = 1;
|
|
|
|
}
|
2016-10-27 18:28:01 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-27 23:35:24 +02:00
|
|
|
|
2016-11-20 02:24:07 +01:00
|
|
|
void sss7_process_tx(void) {
|
2016-10-27 23:35:24 +02:00
|
|
|
if(sss7_tx_last_ack) {
|
|
|
|
uint8_t byte;
|
2016-12-01 00:14:40 +01:00
|
|
|
switch((int) sss7_state) {
|
2016-10-27 23:35:24 +02:00
|
|
|
case SSS7_TX_HEADER:
|
|
|
|
sss7_send_byte(SSS7_HEADER[1]);
|
|
|
|
sss7_state = SSS7_TX_PAYLOAD;
|
|
|
|
sss7_tx_pos = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SSS7_TX_PAYLOAD:
|
|
|
|
byte = sss7_tx_buffer[sss7_tx_pos];
|
|
|
|
sss7_send_byte(byte);
|
|
|
|
sss7_tx_pos++;
|
|
|
|
|
|
|
|
if(sss7_tx_pos >= SSS7_PAYLOAD_SIZE) {
|
|
|
|
sss7_state = SSS7_TX_CRC;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SSS7_TX_CRC:
|
|
|
|
sss7_send_byte(sss7_tx_crc);
|
|
|
|
sss7_state = SSS7_IDLE;
|
|
|
|
break;
|
2016-10-30 02:04:35 +02:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2016-10-27 23:35:24 +02:00
|
|
|
}
|
2016-10-27 18:28:01 +02:00
|
|
|
}
|
2016-10-27 23:35:24 +02:00
|
|
|
else {
|
|
|
|
sss7_tx_failed = 1;
|
|
|
|
sss7_state = SSS7_IDLE;
|
|
|
|
}
|
2016-10-27 18:28:01 +02:00
|
|
|
}
|
|
|
|
|
2016-11-21 09:42:22 +01:00
|
|
|
void sss7_process_ticks(uint16_t ticks) {
|
|
|
|
if(sss7_state != SSS7_IDLE) {
|
|
|
|
sss7_timeout_counter = sss7_timeout_counter + ticks;
|
|
|
|
|
|
|
|
if(sss7_timeout_counter > sss7_timeout) {
|
2016-12-01 00:14:40 +01:00
|
|
|
switch((int) sss7_state) {
|
2016-11-21 09:42:22 +01:00
|
|
|
case SSS7_TX_HEADER:
|
|
|
|
case SSS7_TX_PAYLOAD:
|
|
|
|
case SSS7_TX_CRC:
|
|
|
|
sss7_tx_failed = 1;
|
|
|
|
default:
|
|
|
|
sss7_state = SSS7_IDLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-20 02:24:07 +01:00
|
|
|
|
2016-10-27 18:28:01 +02:00
|
|
|
void sss7_get_received(uint8_t msg[SSS7_PAYLOAD_SIZE]) {
|
|
|
|
if(sss7_has_received()) {
|
2016-11-29 19:18:42 +01:00
|
|
|
memcpy(msg, sss7_rx_buffer[sss7_rx_buffer_read], SSS7_PAYLOAD_SIZE);
|
|
|
|
sss7_rx_buffer_read = (sss7_rx_buffer_read + 1) % SSS7_RX_BUFFER_SIZE;
|
2016-10-27 18:28:01 +02:00
|
|
|
};
|
|
|
|
}
|