diff --git a/Modem/Modem_user.mk b/Modem/Modem_user.mk index 4762ddb..bf15fbe 100644 --- a/Modem/Modem_user.mk +++ b/Modem/Modem_user.mk @@ -12,6 +12,7 @@ Modem_USER_CSRC = \ $(Modem_SRC_PATH)/main.c \ $(Modem_HW_PATH)/hardware.c \ $(Modem_HW_PATH)/afsk.c \ + $(Modem_HW_PATH)/protocol/mp1.c \ bertos/net/ax25.c \ bertos/algo/crc_ccitt.c \ # diff --git a/Modem/main.c b/Modem/main.c index 4fae4e4..c9fd9ca 100644 --- a/Modem/main.c +++ b/Modem/main.c @@ -2,7 +2,8 @@ #include #include -#include "afsk.h" +#include "afsk.h" // Header for AFSK modem +#include "protocol/mp1.h" // Header for MP.1 protocol #include #include @@ -13,6 +14,8 @@ static Afsk afsk; static Serial ser; +static MP1 mp1; + #define ADC_CH 0 @@ -32,6 +35,10 @@ static void message_callback(struct AX25Msg *msg) } /////////////////////////////////////////////// +static void mp1Callback(struct MP1Packet *packet) { + kfile_printf(&ser.fd, "\nMP1 Packet Received:\n"); + kfile_printf(&ser.fd, "%.*s\r\n", packet->dataLength, packet->data); +} static void init(void) { @@ -41,6 +48,8 @@ static void init(void) afsk_init(&afsk, ADC_CH, 0); ax25_init(&ax25, &afsk.fd, message_callback); + mp1Init(&mp1, &afsk.fd, mp1Callback); + ser_init(&ser, SER_UART0); ser_setbaudrate(&ser, 115200); @@ -53,11 +62,13 @@ int main(void) while (1) { - // Raw output, no protocol - if (!fifo_isempty(&afsk.rxFifo)) { - char c = fifo_pop(&afsk.rxFifo); - kprintf("%c", c); - } + // Raw read, no protocol + // if (!fifo_isempty(&afsk.rxFifo)) { + // char c = fifo_pop(&afsk.rxFifo); + // kprintf("%c", c); + // } + + mp1Poll(&mp1); // Use AX.25 to send test data if (timer_clock() - start > ms_to_ticks(4000L)) diff --git a/Modem/protocol/mp1.c b/Modem/protocol/mp1.c new file mode 100644 index 0000000..59d4dd9 --- /dev/null +++ b/Modem/protocol/mp1.c @@ -0,0 +1,87 @@ +#include "mp1.h" +#include +//#include + +static void mp1Decode(MP1 *mp1) { + MP1Packet packet; // A decoded packet struct + uint8_t *buffer = mp1->buffer; // Get the buffer from the protocol context + + packet.dataLength = mp1->packetLength; + packet.data = buffer; + + if (mp1->callback) mp1->callback(&packet); +} + +void mp1Poll(MP1 *mp1) { + int byte; + + // Read bytes from the modem until we reach EOF + while ((byte = kfile_getc(mp1->modem)) != EOF) { + if (!mp1->escape && byte == HDLC_FLAG) { + // We are not in an escape sequence and we + // found a HDLC_FLAG. This can mean two things: + if (mp1->packetLength >= MP1_MIN_FRAME_LENGTH) { + // We already have more data than the minimum + // frame length, which means the flag signifies + // the end of the packet. Pass control to the + // decoder. + mp1Decode(mp1); + } + // If the above is not the case, this must be the + // beginning of a frame + mp1->reading = true; + mp1->packetLength = 0; + // We have indicated that we are reading, + // and reset the length counter. Now we'll + // continue to the next byte. + continue; + } + + if (!mp1->escape && byte == HDLC_RESET) { + // Not good, we got a reset. The transmitting + // party may have encountered an error. We'll + // stop receiving this packet immediately. + mp1->reading = false; + continue; + } + + if (!mp1->escape && byte == AX25_ESC) { + // We found an escape character. We'll set + // the escape seqeunce indicator so we don't + // interpret the next byte as a reset or flag + mp1->escape = true; + continue; + } + + // Now let's get to the actual reading of the data + if (mp1->reading) { + if (mp1->packetLength < MP1_MAX_FRAME_LENGTH) { + // If the length of the current incoming frame is + // still less than our max length, put the incoming + // byte in the buffer. + mp1->buffer[mp1->packetLength++] = byte; + } else { + // If not, we have a problem: The buffer has overrun + // We need to stop receiving, and the packet will be + // dropped :( + mp1->reading = false; + } + } + // We need to set the escape sequence indicator back + // to false after each byte. + mp1->escape = false; + } + + if (kfile_error(mp1->modem)) { + // If there was an error from the modem, we'll be rude + // and just reset it. No error handling is done for now. + kfile_clearerr(mp1->modem); + } +} + +void mp1Init(MP1 *mp1, KFile *modem, mp1_callback_t callback) { + // Allocate memory for our protocol "object" + memset(mp1, 0, sizeof(*mp1)); + mp1->modem = modem; + mp1->callback = callback; +} \ No newline at end of file diff --git a/Modem/protocol/mp1.h b/Modem/protocol/mp1.h new file mode 100644 index 0000000..c439768 --- /dev/null +++ b/Modem/protocol/mp1.h @@ -0,0 +1,43 @@ +#ifndef PROTOCOL_MP1 +#define PROTOCOL_MP1 + +#include +#include + +// Frame sizing +#define MP1_MIN_FRAME_LENGTH 1 +#define MP1_MAX_FRAME_LENGTH 300 + +// We need to know some basic HDLC flag bytes +#define HDLC_FLAG 0x7E +#define HDLC_RESET 0x7F +#define AX25_ESC 0x1B + +// Just a forward declaration that this struct exists +struct MP1Packet; + +// The type of a callback function for passing +// back a decoded packet +typedef void (*mp1_callback_t)(struct MP1Packet *packet); + +// Struct for a protocol context +typedef struct MP1 { + uint8_t buffer[MP1_MAX_FRAME_LENGTH]; // A buffer for incoming packets + KFile *modem; // KFile access to the modem + size_t packetLength; // Counter for received packet length + mp1_callback_t callback; // The function to call when a packet has been received + bool reading; // True when we have seen a HDLC flag + bool escape; // We need to know if we are in an escape sequence +} MP1; + +// A struct encapsulating a network packet +typedef struct MP1Packet { + const uint8_t *data; // Pointer to the actual data in the packet + size_t dataLength; // The length of the received data +} MP1Packet; + +void mp1Init(MP1 *mp1, KFile *modem, mp1_callback_t callback); +void mp1Poll(MP1 *mp1); +void mp1Send(MP1 *mp1, const void *_buffer, size_t length); + +#endif \ No newline at end of file diff --git a/buildrev.h b/buildrev.h index df4ea1b..733e150 100644 --- a/buildrev.h +++ b/buildrev.h @@ -1,2 +1,2 @@ -#define VERS_BUILD 126 +#define VERS_BUILD 136 #define VERS_HOST "vixen" diff --git a/flash b/flash index f0e8e15..4a0a4f1 100755 --- a/flash +++ b/flash @@ -1,2 +1,2 @@ #!/bin/bash -avrdude -p m328p -c arduino -P /dev/ttyACM$1 -b 115200 -F -U flash:w:images/Modem.hex +avrdude -p m328p -c arduino -P /dev/tty$1 -b 115200 -F -U flash:w:images/Modem.hex