From 85286ad46743ef5baf8e9c17b977b05f6ddb3231 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Wed, 16 Apr 2014 14:06:03 +0200 Subject: [PATCH] Interleaver implemented --- Modem/config.h | 6 ++ Modem/main.c | 10 +-- Modem/protocol/mp1.c | 200 ++++++++++++++++++++++++++++++++++--------- Modem/protocol/mp1.h | 4 + buildrev.h | 2 +- 5 files changed, 173 insertions(+), 49 deletions(-) diff --git a/Modem/config.h b/Modem/config.h index c2d238f..c19edc8 100644 --- a/Modem/config.h +++ b/Modem/config.h @@ -2,6 +2,12 @@ #ifndef FSK_CFG #define FSK_CFG +// Debug & test options +#define SERIAL_DEBUG true +#define PASSALL false +#define AUTOREPLY false + +// Modem options #define CONFIG_AFSK_RX_BUFLEN 64 // The size of the modems receive buffer #define CONFIG_AFSK_TX_BUFLEN 64 // The size of the modems transmit buffer #define CONFIG_AFSK_DAC_SAMPLERATE 9600 // The samplerate of the DAC. Note that diff --git a/Modem/main.c b/Modem/main.c index 94e6eee..65b96d4 100644 --- a/Modem/main.c +++ b/Modem/main.c @@ -35,7 +35,7 @@ static Serial ser; // Declare a serial interface struct static uint8_t serialBuffer[MP1_MAX_FRAME_LENGTH]; // This is a buffer for incoming serial data static int sbyte; // For holding byte read from serial port -static int serialLen = 0; // Counter for counting length of data from serial +static size_t serialLen = 0; // Counter for counting length of data from serial static bool sertx = false; // Flag signifying whether it's time to send data // Received on the serial port. @@ -50,12 +50,10 @@ static bool sertx = false; // Flag signifying whether it's time to send da static void mp1Callback(struct MP1Packet *packet) { kfile_printf(&ser.fd, "%.*s\n", packet->dataLength, packet->data); - if (packet->data[0]-128 == 'R' && packet->data[1]-128 == 'Q') { + if (AUTOREPLY && packet->data[0]-128 == 'R' && packet->data[1]-128 == 'Q') { timer_delay(1000); mp1Send(&mp1, TEST_PACKET, sizeof(TEST_PACKET)); } - - //kprintf("%.*s\n", packet->dataLength, packet->data); } // Simple initialization function. @@ -63,8 +61,6 @@ static void init(void) { // Enable interrupts IRQ_ENABLE; - // Initialize BertOS debug bridge - // kdbg_init(); // Initialize hardware timers timer_init(); @@ -117,8 +113,6 @@ int main(void) // If one of the above conditions were actually the // case, it means we have to transmit, se we set // transmission flag to true. - serialBuffer[serialLen] = sbyte; - serialLen++; sertx = true; } } diff --git a/Modem/protocol/mp1.c b/Modem/protocol/mp1.c index 9afb2ce..40ca99f 100644 --- a/Modem/protocol/mp1.c +++ b/Modem/protocol/mp1.c @@ -1,5 +1,6 @@ #include "mp1.h" #include "hardware.h" +#include "config.h" #include #include @@ -12,6 +13,7 @@ static bool sendParityBlock = false; // FIXME: Describe this +INLINE bool GET_BIT(uint8_t byte, int n) { return (byte & (1 << (8-n))) == (1 << (8-n)); } INLINE bool BIT(uint8_t byte, int n) { return ((byte & BV(n-1))>>(n-1)); } static uint8_t mp1ParityBlock(uint8_t first, uint8_t other) { uint8_t parity = 0x00; @@ -65,6 +67,44 @@ static void mp1Decode(MP1 *mp1) { if (mp1->callback) mp1->callback(&packet); } +// Interleaved: +// abcabcab cabcabca bcabcabc +// 11144477 22255578 63336688 +// +// 0 1 2 +static void mp1Deinterleave(MP1 *mp1) { + uint8_t a = (GET_BIT(mp1->interleaveIn[0], 1) << 7) + + (GET_BIT(mp1->interleaveIn[1], 2) << 6) + + (GET_BIT(mp1->interleaveIn[2], 3) << 5) + + (GET_BIT(mp1->interleaveIn[0], 4) << 4) + + (GET_BIT(mp1->interleaveIn[1], 5) << 3) + + (GET_BIT(mp1->interleaveIn[2], 6) << 2) + + (GET_BIT(mp1->interleaveIn[0], 7) << 1) + + (GET_BIT(mp1->interleaveIn[1], 8)); + + uint8_t b = (GET_BIT(mp1->interleaveIn[0], 2) << 7) + + (GET_BIT(mp1->interleaveIn[1], 3) << 6) + + (GET_BIT(mp1->interleaveIn[2], 4) << 5) + + (GET_BIT(mp1->interleaveIn[0], 5) << 4) + + (GET_BIT(mp1->interleaveIn[1], 6) << 3) + + (GET_BIT(mp1->interleaveIn[2], 1) << 2) + + (GET_BIT(mp1->interleaveIn[0], 8) << 1) + + (GET_BIT(mp1->interleaveIn[2], 7)); + + uint8_t c = (GET_BIT(mp1->interleaveIn[0], 3) << 7) + + (GET_BIT(mp1->interleaveIn[1], 1) << 6) + + (GET_BIT(mp1->interleaveIn[2], 2) << 5) + + (GET_BIT(mp1->interleaveIn[0], 6) << 4) + + (GET_BIT(mp1->interleaveIn[1], 4) << 3) + + (GET_BIT(mp1->interleaveIn[2], 5) << 2) + + (GET_BIT(mp1->interleaveIn[1], 7) << 1) + + (GET_BIT(mp1->interleaveIn[2], 8)); + + mp1->interleaveIn[0] = a; + mp1->interleaveIn[1] = b; + mp1->interleaveIn[2] = c; +} + //////////////////////////////////////////////////////////// // The Poll function reads data from the modem, handles // // frame recognition and passes data on to higher layers // @@ -84,8 +124,17 @@ void mp1Poll(MP1 *mp1) { if (mp1->readLength % 3 == 0) { + // Put bytes in deinterleave buffer + mp1->interleaveIn[0] = mp1->buffer[mp1->packetLength-2]; + mp1->interleaveIn[1] = mp1->buffer[mp1->packetLength-1]; + mp1->interleaveIn[2] = byte; + + mp1Deinterleave(mp1); + mp1->buffer[mp1->packetLength-2] = mp1->interleaveIn[0]; + mp1->buffer[mp1->packetLength-1] = mp1->interleaveIn[1]; + mp1->calculatedParity = mp1ParityBlock(mp1->buffer[mp1->packetLength-2], mp1->buffer[mp1->packetLength-1]); - uint8_t syndrome = mp1->calculatedParity ^ byte; + uint8_t syndrome = mp1->calculatedParity ^ mp1->interleaveIn[2]; if (syndrome == 0x00) { // No problems! } else { @@ -109,14 +158,16 @@ void mp1Poll(MP1 *mp1) { if (s == 11) correction = 0x40; if (s == 12) correction = 0x80; - if (correction != 0x00) { - mp1->checksum_in ^= correction; - } mp1->buffer[mp1->packetLength-(2-i)] ^= correction; if (s != 0) mp1->correctionsMade += 1; } } + + mp1->checksum_in ^= mp1->buffer[mp1->packetLength-2]; + mp1->checksum_in ^= mp1->buffer[mp1->packetLength-1]; + //mp1->checksum_in ^= mp1->interleaveIn[2]; + continue; } } @@ -131,15 +182,16 @@ void mp1Poll(MP1 *mp1) { // the end of the packet. Pass control to the // decoder. if ((mp1->checksum_in & 0xff) == 0x00) { - kprintf("[CHK-OK] [C=%d] ", mp1->correctionsMade); + if (SERIAL_DEBUG) kprintf("[CHK-OK] [C=%d] ", mp1->correctionsMade); mp1Decode(mp1); } else { // Checksum was incorrect, we don't do anything, // but you can enable the decode anyway, if you // need it for testing or debugging - // kprintf("[ER] [%d] ", mp1->checksum_in); - kprintf("[CHK-ER] [C=%d] ", mp1->correctionsMade); - mp1Decode(mp1); + if (PASSALL) { + if (SERIAL_DEBUG) kprintf("[CHK-ER] [C=%d] ", mp1->correctionsMade); + mp1Decode(mp1); + } } } // If the above is not the case, this must be the @@ -180,7 +232,7 @@ void mp1Poll(MP1 *mp1) { // If the length of the current incoming frame is // still less than our max length, put the incoming // byte in the buffer. - mp1->checksum_in = mp1->checksum_in ^ byte; + // mp1->checksum_in = mp1->checksum_in ^ byte; mp1->buffer[mp1->packetLength++] = byte; } else { // If not, we have a problem: The buffer has overrun @@ -202,8 +254,9 @@ void mp1Poll(MP1 *mp1) { } } -// FIXME: Desribe additions here -static void mp1Putbyte(MP1 *mp1, uint8_t byte) { +// This is called to actually send the bytes +// after they have been interleaved +static void mp1WriteByte(MP1 *mp1, uint8_t byte) { // If we are sending something that looks // like an HDLC special byte, send an escape // character first @@ -212,37 +265,118 @@ static void mp1Putbyte(MP1 *mp1, uint8_t byte) { byte == AX25_ESC) { kfile_putc(AX25_ESC, mp1->modem); } - kfile_putc(byte, mp1->modem); +} + +/////////////////////////////// +// Interleave-table // +/////////////////////////////// +// +// Non-interleaved: +// aaaaaaaa bbbbbbbb cccccccc +// 12345678 12345678 12345678 +// M L +// S S +// B B +// +// Interleaved: +// abcabcab cabcabca bcabcabc +// 11144477 22255578 63336688 +// +// +// 3bit burst error patterns: +// X||||||| X||||||| X||||||| +// |||X|||| X||||||| X||||||| +// |||X|||| |||X|||| X||||||| +// |||X|||| |||X|||| |||X|||| +// ||||||X| |||X|||| |||X|||| +// ||||||X| ||||||X| |||X|||| +// ||||||X| ||||||X| |X|||||| +// |X|||||| ||||||X| |X|||||| +// |X|||||| |X|||||| |X|||||| +// |X|||||| |X|||||| ||||X||| +// ||||X||| |X|||||| ||||X||| +// ||||X||| ||||X||| ||||X||| +// ||||X||| ||||X||| ||||||X| +// |||||||X ||||X||| ||||||X| +// |||||||X |||||X|| ||||||X| +// |||||||X |||||X|| ||X||||| +// ||X||||| |||||X|| ||X||||| +// ||X||||| ||X||||| ||X||||| +// ||X||||| ||X||||| |||||X|| +// |||||X|| ||X||||| |||||X|| +// |||||X|| |||||||X |||||X|| +// |||||X|| |||||||X |||||||X +// +/////////////////////////////// + +static void mp1Interleave(MP1 *mp1, uint8_t byte) { + mp1->interleaveOut[mp1->interleaveCounter] = byte; + mp1->interleaveCounter++; + if (mp1->interleaveCounter == 3) { + // We have three bytes in the buffer and + // are ready to interleave them. + + uint8_t a = (GET_BIT(mp1->interleaveOut[0], 1) << 7) + + (GET_BIT(mp1->interleaveOut[1], 1) << 6) + + (GET_BIT(mp1->interleaveOut[2], 1) << 5) + + (GET_BIT(mp1->interleaveOut[0], 4) << 4) + + (GET_BIT(mp1->interleaveOut[1], 4) << 3) + + (GET_BIT(mp1->interleaveOut[2], 4) << 2) + + (GET_BIT(mp1->interleaveOut[0], 7) << 1) + + (GET_BIT(mp1->interleaveOut[1], 7)); + mp1WriteByte(mp1, a); + + uint8_t b = (GET_BIT(mp1->interleaveOut[2], 2) << 7) + + (GET_BIT(mp1->interleaveOut[0], 2) << 6) + + (GET_BIT(mp1->interleaveOut[1], 2) << 5) + + (GET_BIT(mp1->interleaveOut[2], 5) << 4) + + (GET_BIT(mp1->interleaveOut[0], 5) << 3) + + (GET_BIT(mp1->interleaveOut[1], 5) << 2) + + (GET_BIT(mp1->interleaveOut[2], 7) << 1) + + (GET_BIT(mp1->interleaveOut[0], 8)); + mp1WriteByte(mp1, b); + + uint8_t c = (GET_BIT(mp1->interleaveOut[1], 6) << 7) + + (GET_BIT(mp1->interleaveOut[2], 3) << 6) + + (GET_BIT(mp1->interleaveOut[0], 3) << 5) + + (GET_BIT(mp1->interleaveOut[1], 3) << 4) + + (GET_BIT(mp1->interleaveOut[2], 6) << 3) + + (GET_BIT(mp1->interleaveOut[0], 6) << 2) + + (GET_BIT(mp1->interleaveOut[1], 8) << 1) + + (GET_BIT(mp1->interleaveOut[2], 8)); + + mp1WriteByte(mp1, c); + // mp1WriteByte(mp1, a); + // mp1WriteByte(mp1, b); + // mp1WriteByte(mp1, c); + + mp1->interleaveCounter = 0; + } +} + +// FIXME: Desribe additions here +static void mp1Putbyte(MP1 *mp1, uint8_t byte) { + //kfile_putc(byte, mp1->modem); + mp1Interleave(mp1, byte); if (sendParityBlock) { uint8_t p = mp1ParityBlock(lastByte, byte); - kfile_putc(p, mp1->modem); + //kfile_putc(p, mp1->modem); + mp1Interleave(mp1, p); } lastByte = byte; sendParityBlock ^= true; } -static void mp1WriteByte(MP1 *mp1, uint8_t byte) { - // If we are sending something that looks - // like an HDLC special byte, send an escape - // character first - if (byte == HDLC_FLAG || - byte == HDLC_RESET || - byte == AX25_ESC) { - kfile_putc(AX25_ESC, mp1->modem); - } - - kfile_putc(byte, mp1->modem); -} - void mp1Send(MP1 *mp1, const void *_buffer, size_t length) { // Get the transmit data buffer const uint8_t *buffer = (const uint8_t *)_buffer; // Initialize checksum mp1->checksum_out = MP1_CHECKSUM_INIT; + mp1->interleaveCounter = 0; // FIXME: // Transmit the HDLC_FLAG to signify start of TX kfile_putc(HDLC_FLAG, mp1->modem); @@ -312,7 +446,6 @@ int freeRam(void) { size_t compress(uint8_t *input, size_t length) { heatshrink_encoder *hse = heatshrink_encoder_alloc(8, 4); if (hse == NULL) { - //kprintf("Could not allocate encoder\n"); return 0; } @@ -322,16 +455,11 @@ size_t compress(uint8_t *input, size_t length) { int status = heatshrink_encoder_finish(hse); if (sunk < length) { - //kprintf("Not all data was sunk into encoder\n"); heatshrink_encoder_free(hse); return 0; } else { - //kprintf("Bytes sunk into HSE: %d\n", length); if (status == HSER_FINISH_MORE) { heatshrink_encoder_poll(hse, compressionBuffer, MP1_MAX_FRAME_LENGTH, &written); - //kprintf("Bytes written into buffer: %d\n", written); - } else { - //kprintf("All input data was sunk, but encoder doesn't have any data for us."); } } @@ -342,28 +470,20 @@ size_t compress(uint8_t *input, size_t length) { size_t decompress(uint8_t *input, size_t length) { heatshrink_decoder *hsd = heatshrink_decoder_alloc(MP1_MAX_FRAME_LENGTH, 8, 4); if (hsd == NULL) { - //kprintf("Could not allocate decoder\n"); return 0; } - //kprintf("\nDecoder allocated. Free RAM: %d bytes\n", freeRam()); - size_t written = 0; size_t sunk = 0; heatshrink_decoder_sink(hsd, input, length, &sunk); int status = heatshrink_decoder_finish(hsd); if (sunk < length) { - //kprintf("Not all data was sunk into decoder\n"); heatshrink_decoder_free(hsd); return 0; } else { - //kprintf("Bytes sunk into HSD: %d\n", length); if (status == HSER_FINISH_MORE) { heatshrink_decoder_poll(hsd, compressionBuffer, MP1_MAX_FRAME_LENGTH, &written); - //kprintf("Bytes written into decompression buffer: %d\n", written); - } else { - //kprintf("All input data was sunk, but the decoder doesn't have any data for us."); } } diff --git a/Modem/protocol/mp1.h b/Modem/protocol/mp1.h index 61b3cdc..499f6a2 100644 --- a/Modem/protocol/mp1.h +++ b/Modem/protocol/mp1.h @@ -7,6 +7,7 @@ // Frame sizing & checksum #define MP1_MIN_FRAME_LENGTH 3 #define MP1_MAX_FRAME_LENGTH 300 +#define MP1_INTERLEAVE_SIZE 3 #define MP1_CHECKSUM_INIT 0xAA // We need to know some basic HDLC flag bytes @@ -45,6 +46,9 @@ typedef struct MP1 { bool escape; // We need to know if we are in an escape sequence bool fecEscape; // fec escape long correctionsMade; // correction count + uint8_t interleaveCounter; // interleave counter + uint8_t interleaveOut[MP1_INTERLEAVE_SIZE]; + uint8_t interleaveIn[MP1_INTERLEAVE_SIZE]; } MP1; // A struct encapsulating a network packet diff --git a/buildrev.h b/buildrev.h index 484351d..86b83e6 100644 --- a/buildrev.h +++ b/buildrev.h @@ -1,2 +1,2 @@ -#define VERS_BUILD 1108 +#define VERS_BUILD 1197 #define VERS_HOST "vixen"