Started general cleanup and added comments
This commit is contained in:
parent
5722ef1b9f
commit
e6b17010f6
|
@ -91,7 +91,7 @@ Initial value: 0x0
|
||||||
### Planned API
|
### Planned API
|
||||||
- **Not final, use with caution**
|
- **Not final, use with caution**
|
||||||
- All calls are non-blocking,
|
- All calls are non-blocking,
|
||||||
any real work should be done by ISRs or an eventloop, which is called peridically.
|
any real work should be done by ISRs or an eventloop, which is called periodically.
|
||||||
|
|
||||||
- **sss7_can_send()**
|
- **sss7_can_send()**
|
||||||
|
|
||||||
|
@ -131,8 +131,8 @@ The files are made avaible under the Creative Commons license rev2.5 Attribution
|
||||||
|
|
||||||
The Chaos InKL logo is licensed CC BY-NC-SA 3.0.
|
The Chaos InKL logo is licensed CC BY-NC-SA 3.0.
|
||||||
|
|
||||||
The seidenstrasse logo and my personal logo are not avaiable under an open licence.
|
The seidenstrasse logo and my personal logo are not available under an open license.
|
||||||
Therefore you should ask for permission before using the seidenstrasse logo in derived works.
|
Therefore you should ask for permission before using the seidenstrasse logo in derived works.
|
||||||
Also please remove my personal logo if I am not involved in your project.
|
Also please remove my personal logo if I am not involved in your project.
|
||||||
|
|
||||||
The schematics and pcb layout files in hardware are released under the *CERN Open Hardware Licence v1.2*.
|
The schematics and pcb layout files in hardware are released under the *CERN Open Hardware License v1.2*.
|
||||||
|
|
|
@ -2,23 +2,47 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Current state
|
||||||
sss7_shared_modfier enum sss7State sss7_state;
|
sss7_shared_modfier enum sss7State sss7_state;
|
||||||
|
|
||||||
uint8_t sss7_rx_buffer[SSS7_RX_BUFFER_SIZE][SSS7_PAYLOAD_SIZE];
|
// Position in the payload for receiving a frame
|
||||||
uint8_t sss7_rx_buffer_write;
|
|
||||||
uint8_t sss7_rx_buffer_read;
|
|
||||||
uint8_t sss7_rx_pos;
|
uint8_t sss7_rx_pos;
|
||||||
|
|
||||||
|
// Buffer for the payload for sending a frame
|
||||||
uint8_t sss7_tx_buffer[SSS7_PAYLOAD_SIZE];
|
uint8_t sss7_tx_buffer[SSS7_PAYLOAD_SIZE];
|
||||||
|
// Position in the payload for sending a frame
|
||||||
uint8_t sss7_tx_pos;
|
uint8_t sss7_tx_pos;
|
||||||
|
// Crc for the payload used for sending a frame
|
||||||
uint8_t sss7_tx_crc;
|
uint8_t sss7_tx_crc;
|
||||||
sss7_shared_modfier uint8_t sss7_tx_failed;
|
// The last byte that has been send, used for collison checks in sss7_process_rx
|
||||||
uint8_t sss7_tx_last_byte;
|
uint8_t sss7_tx_last_byte;
|
||||||
|
// Flag set by sss7_process_rx to indicate that the received byte was sss7_tx_last_byte
|
||||||
uint8_t sss7_tx_last_ack;
|
uint8_t sss7_tx_last_ack;
|
||||||
|
|
||||||
sss7_shared_modfier uint8_t sss7_timeout_counter;
|
// Flag to indicate wheter the last attempt to send a frame failed
|
||||||
|
sss7_shared_modfier uint8_t sss7_tx_failed;
|
||||||
|
|
||||||
|
// Counter that counts milliseconds since the last byte was received
|
||||||
|
// Incremented and checked by sss7_process_ticks.
|
||||||
|
// Reset by sss7_process_rx.
|
||||||
|
uint8_t sss7_timeout_counter;
|
||||||
|
|
||||||
|
|
||||||
|
// Buffers used for receiving payloads with space for SSS7_RX_BUFFER_SIZE payloads
|
||||||
|
uint8_t sss7_rx_buffer[SSS7_RX_BUFFER_SIZE][SSS7_PAYLOAD_SIZE];
|
||||||
|
// Payload in the buffer to write the received bytes to
|
||||||
|
// Note: The payload at sss7_rx_buffer_write can be modified at any time
|
||||||
|
// and should therefore never be read by sss7_get_received.
|
||||||
|
sss7_shared_modfier uint8_t sss7_rx_buffer_write;
|
||||||
|
// Next payload to read by sss7_get_received
|
||||||
|
sss7_shared_modfier uint8_t sss7_rx_buffer_read;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize sss7 state variables.
|
||||||
|
* Resets all buffer positions to 0 and sets state to idle.
|
||||||
|
*/
|
||||||
void sss7_init(void) {
|
void sss7_init(void) {
|
||||||
sss7_state = SSS7_IDLE;
|
sss7_state = SSS7_IDLE;
|
||||||
|
|
||||||
|
@ -32,6 +56,12 @@ void sss7_init(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal function to calculate the payload crc.
|
||||||
|
* Uses the Maxim iButton 8-bit CRC also known as crc-8-maxim
|
||||||
|
* Polynomial: x^8 + x^5 + x^4 + 1 (0x8C)
|
||||||
|
* Initial value: 0x0
|
||||||
|
*/
|
||||||
static inline uint8_t sss7_payload_crc(uint8_t buffer[SSS7_PAYLOAD_SIZE]) {
|
static inline uint8_t sss7_payload_crc(uint8_t buffer[SSS7_PAYLOAD_SIZE]) {
|
||||||
uint8_t crc = 0;
|
uint8_t crc = 0;
|
||||||
|
|
||||||
|
@ -52,6 +82,10 @@ static inline uint8_t sss7_payload_crc(uint8_t buffer[SSS7_PAYLOAD_SIZE]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal function to send a single byte.
|
||||||
|
* Assumes that it can use uart_put_byte to actually send the byte.
|
||||||
|
*/
|
||||||
static inline void sss7_send_byte(uint8_t byte) {
|
static inline void sss7_send_byte(uint8_t byte) {
|
||||||
sss7_tx_last_ack = 0;
|
sss7_tx_last_ack = 0;
|
||||||
sss7_tx_last_byte = byte;
|
sss7_tx_last_byte = byte;
|
||||||
|
@ -59,6 +93,9 @@ static inline void sss7_send_byte(uint8_t byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Triggers the transmission of a frame.
|
||||||
|
*/
|
||||||
void sss7_send(uint8_t msg[SSS7_PAYLOAD_SIZE]) {
|
void sss7_send(uint8_t msg[SSS7_PAYLOAD_SIZE]) {
|
||||||
// Check that we can send, because we will overwritte the buffer
|
// Check that we can send, because we will overwritte the buffer
|
||||||
if(sss7_state != SSS7_IDLE) {
|
if(sss7_state != SSS7_IDLE) {
|
||||||
|
@ -78,15 +115,26 @@ void sss7_send(uint8_t msg[SSS7_PAYLOAD_SIZE]) {
|
||||||
sss7_send_byte(SSS7_HEADER[0]);
|
sss7_send_byte(SSS7_HEADER[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler function for received bytes.
|
||||||
|
* Should be called for every received byte, by either interrupts or an eventloop.
|
||||||
|
* It also resets the timeout timer.
|
||||||
|
* uart_get_byte() is used to retreive the received byte.
|
||||||
|
*
|
||||||
|
* Note: This handler should by called BEFORE sss7_process_tx when sending.
|
||||||
|
*/
|
||||||
void sss7_process_rx(void) {
|
void sss7_process_rx(void) {
|
||||||
uint8_t byte = uart_get_byte();
|
uint8_t byte = uart_get_byte();
|
||||||
uint8_t crc = 0;
|
uint8_t crc = 0;
|
||||||
uint8_t next_buffer_write = 0;
|
uint8_t next_buffer_write = 0;
|
||||||
|
|
||||||
|
// Reset timeout counter
|
||||||
sss7_timeout_counter = 0;
|
sss7_timeout_counter = 0;
|
||||||
|
|
||||||
switch((int) sss7_state) {
|
switch((int) sss7_state) {
|
||||||
|
// Handle the states for reiceiving a frame first
|
||||||
case SSS7_IDLE:
|
case SSS7_IDLE:
|
||||||
|
// First received byte should be the first header byte
|
||||||
if(byte == SSS7_HEADER[0]) {
|
if(byte == SSS7_HEADER[0]) {
|
||||||
sss7_state = SSS7_RX_HEADER;
|
sss7_state = SSS7_RX_HEADER;
|
||||||
}
|
}
|
||||||
|
@ -96,6 +144,7 @@ void sss7_process_rx(void) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSS7_RX_HEADER:
|
case SSS7_RX_HEADER:
|
||||||
|
// Second received byte should be the second header byte
|
||||||
if(byte == SSS7_HEADER[1]) {
|
if(byte == SSS7_HEADER[1]) {
|
||||||
sss7_state = SSS7_RX_PAYLOAD;
|
sss7_state = SSS7_RX_PAYLOAD;
|
||||||
sss7_rx_pos = 0;
|
sss7_rx_pos = 0;
|
||||||
|
@ -106,31 +155,44 @@ void sss7_process_rx(void) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSS7_RX_PAYLOAD:
|
case SSS7_RX_PAYLOAD:
|
||||||
|
// Receive the payload
|
||||||
sss7_rx_buffer[sss7_rx_buffer_write][sss7_rx_pos] = byte;
|
sss7_rx_buffer[sss7_rx_buffer_write][sss7_rx_pos] = byte;
|
||||||
sss7_rx_pos++;
|
sss7_rx_pos++;
|
||||||
|
// Check if the payload has been fully received
|
||||||
if(sss7_rx_pos >= SSS7_PAYLOAD_SIZE) {
|
if(sss7_rx_pos >= SSS7_PAYLOAD_SIZE) {
|
||||||
sss7_state = SSS7_RX_CRC;
|
sss7_state = SSS7_RX_CRC;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSS7_RX_CRC:
|
case SSS7_RX_CRC:
|
||||||
|
// Last byte of the frame
|
||||||
crc = sss7_payload_crc(sss7_rx_buffer[sss7_rx_buffer_write]);
|
crc = sss7_payload_crc(sss7_rx_buffer[sss7_rx_buffer_write]);
|
||||||
|
|
||||||
|
// Calculate the next rx buffer position to use
|
||||||
next_buffer_write = (sss7_rx_buffer_write + 1) % SSS7_RX_BUFFER_SIZE;
|
next_buffer_write = (sss7_rx_buffer_write + 1) % SSS7_RX_BUFFER_SIZE;
|
||||||
// Ensure CRC is okay and we don't overwrite other frames
|
// If the crc is not okay or there are no free buffer positions left,
|
||||||
|
// the next frame will be written to the same rx buffer postion.
|
||||||
|
// This effectively drops the currrent frame.
|
||||||
if(byte == crc && next_buffer_write != sss7_rx_buffer_read) {
|
if(byte == crc && next_buffer_write != sss7_rx_buffer_read) {
|
||||||
sss7_rx_buffer_write = next_buffer_write;
|
sss7_rx_buffer_write = next_buffer_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Go back to idle state
|
||||||
sss7_state = SSS7_IDLE;
|
sss7_state = SSS7_IDLE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// all the TX states
|
// Handle all the TX states
|
||||||
default:
|
default:
|
||||||
|
// Collision check:
|
||||||
|
// If the byte received is not the last byte sent, something went wrong
|
||||||
if(byte != sss7_tx_last_byte) {
|
if(byte != sss7_tx_last_byte) {
|
||||||
sss7_state = SSS7_IDLE;
|
// Set the failure flag
|
||||||
sss7_tx_failed = 1;
|
sss7_tx_failed = 1;
|
||||||
|
// Reset to state to idle
|
||||||
|
sss7_state = SSS7_IDLE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// Set the ack flag which is checked by sss7_process_tx
|
||||||
sss7_tx_last_ack = 1;
|
sss7_tx_last_ack = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -138,42 +200,75 @@ void sss7_process_rx(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler function for sent bytes.
|
||||||
|
* Should be called for every compltely sent byte, by either interrupts or an eventloop.
|
||||||
|
* Uses uart_put_byte() to send the next byte.
|
||||||
|
*
|
||||||
|
* Note: This handler should by called AFTER sss7_process_rx when sending.
|
||||||
|
*/
|
||||||
void sss7_process_tx(void) {
|
void sss7_process_tx(void) {
|
||||||
|
// This handler is called since a byte has been sent and it should have been,
|
||||||
|
// read back from the bus and handled by sss7_process_rx by now.
|
||||||
|
// So if the last byte sent was acked by everthing is alright
|
||||||
if(sss7_tx_last_ack) {
|
if(sss7_tx_last_ack) {
|
||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
switch((int) sss7_state) {
|
switch((int) sss7_state) {
|
||||||
case SSS7_TX_HEADER:
|
case SSS7_TX_HEADER:
|
||||||
|
// First byte of the frame is already sent by sss7_send_byte,
|
||||||
|
// this handler is called since its transmission completed.
|
||||||
|
// Therefore the second header byte is sent.
|
||||||
sss7_send_byte(SSS7_HEADER[1]);
|
sss7_send_byte(SSS7_HEADER[1]);
|
||||||
sss7_state = SSS7_TX_PAYLOAD;
|
// Reset the position inside the payload
|
||||||
sss7_tx_pos = 0;
|
sss7_tx_pos = 0;
|
||||||
|
sss7_state = SSS7_TX_PAYLOAD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSS7_TX_PAYLOAD:
|
case SSS7_TX_PAYLOAD:
|
||||||
|
// Send the next payload byte and increment position
|
||||||
byte = sss7_tx_buffer[sss7_tx_pos];
|
byte = sss7_tx_buffer[sss7_tx_pos];
|
||||||
sss7_send_byte(byte);
|
sss7_send_byte(byte);
|
||||||
sss7_tx_pos++;
|
sss7_tx_pos++;
|
||||||
|
|
||||||
|
// All the payload bytes are sent, continue with crc
|
||||||
if(sss7_tx_pos >= SSS7_PAYLOAD_SIZE) {
|
if(sss7_tx_pos >= SSS7_PAYLOAD_SIZE) {
|
||||||
sss7_state = SSS7_TX_CRC;
|
sss7_state = SSS7_TX_CRC;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSS7_TX_CRC:
|
case SSS7_TX_CRC:
|
||||||
|
// Send the crc precalculated by sss_send
|
||||||
sss7_send_byte(sss7_tx_crc);
|
sss7_send_byte(sss7_tx_crc);
|
||||||
|
// Reset the state to idle
|
||||||
sss7_state = SSS7_IDLE;
|
sss7_state = SSS7_IDLE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
// Controlflow should never ever end up here.
|
||||||
|
// Calling the tx handler while being in rx state is messed up.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If the byte was not acked, something went wrong
|
||||||
else {
|
else {
|
||||||
|
// Set failure flag
|
||||||
sss7_tx_failed = 1;
|
sss7_tx_failed = 1;
|
||||||
|
// Reset state to idle
|
||||||
sss7_state = SSS7_IDLE;
|
sss7_state = SSS7_IDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler function for timeout timer updates.
|
||||||
|
* Should be called every once in a while either by interrupts by an eventloop.
|
||||||
|
* The ticks parameter is the number of milliseconds that have passed since the last invocation.
|
||||||
|
*
|
||||||
|
* The timeout basically resolves the scenario where an partial frame is received without errors,
|
||||||
|
* but never finished.
|
||||||
|
*/
|
||||||
void sss7_process_ticks(uint16_t ticks) {
|
void sss7_process_ticks(uint16_t ticks) {
|
||||||
|
// There are no timeouts in idle state.
|
||||||
if(sss7_state != SSS7_IDLE) {
|
if(sss7_state != SSS7_IDLE) {
|
||||||
sss7_timeout_counter = sss7_timeout_counter + ticks;
|
sss7_timeout_counter = sss7_timeout_counter + ticks;
|
||||||
|
|
||||||
|
@ -190,10 +285,15 @@ void sss7_process_ticks(uint16_t ticks) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to retreive a received frame from the rx buffer.
|
||||||
|
*/
|
||||||
void sss7_get_received(uint8_t msg[SSS7_PAYLOAD_SIZE]) {
|
void sss7_get_received(uint8_t msg[SSS7_PAYLOAD_SIZE]) {
|
||||||
|
// Make sure that sss7_rx_buffer_write != sss7_rx_buffer_read still holds
|
||||||
if(sss7_has_received()) {
|
if(sss7_has_received()) {
|
||||||
|
// Copy the payload
|
||||||
memcpy(msg, sss7_rx_buffer[sss7_rx_buffer_read], SSS7_PAYLOAD_SIZE);
|
memcpy(msg, sss7_rx_buffer[sss7_rx_buffer_read], SSS7_PAYLOAD_SIZE);
|
||||||
|
// Move to the next payload in the buffer
|
||||||
sss7_rx_buffer_read = (sss7_rx_buffer_read + 1) % SSS7_RX_BUFFER_SIZE;
|
sss7_rx_buffer_read = (sss7_rx_buffer_read + 1) % SSS7_RX_BUFFER_SIZE;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,8 @@ const static uint16_t sss7_timeout_increment = 1;
|
||||||
|
|
||||||
extern sss7_shared_modfier enum sss7State sss7_state;
|
extern sss7_shared_modfier enum sss7State sss7_state;
|
||||||
extern sss7_shared_modfier uint8_t sss7_tx_failed;
|
extern sss7_shared_modfier uint8_t sss7_tx_failed;
|
||||||
extern uint8_t sss7_rx_buffer_write;
|
extern sss7_shared_modfier uint8_t sss7_rx_buffer_write;
|
||||||
extern uint8_t sss7_rx_buffer_read;
|
extern sss7_shared_modfier uint8_t sss7_rx_buffer_read;
|
||||||
|
|
||||||
|
|
||||||
void sss7_process_rx(void);
|
void sss7_process_rx(void);
|
||||||
|
|
Loading…
Reference in New Issue