/* * High Speed modem to transfer data in a 2,7kHz SSB channel * ========================================================= * Author: DJ0ABR * * (c) DJ0ABR * www.dj0abr.de * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include "qo100modem.h" void Insert(uint8_t bit); uint8_t *FindDatablock(); uint8_t rxbuffer[UDPBLOCKLEN*8/2+100]; // 3...bits per symbol QPSK, enough space also for QPSK and 8PSK, +100 ... reserve, just to be sure uint8_t rx_status = 0; int framecounter = 0; int lastframenum = 0; // header for TX, uint8_t TXheaderbytes[HEADERLEN] = {0x53, 0xe1, 0xa6}; // corresponds to these QPSK symbols: // bits: 01010011 11100001 10100110 // QPSK: // syms: 1 1 0 3 3 2 0 1 2 2 1 2 // 8PSK: // syms: 2 4 7 6 0 6 4 6 // QPSK // each header has 12 symbols // we have 4 constellations uint8_t QPSK_headertab[4][HEADERLEN*8/2]; // 8PSK // each header has 12 symbols // we have 8 constellations uint8_t _8PSK_headertab[8][HEADERLEN*8/3]; // init header tables void init_packer() { // create the QPSK symbol table for the HEADER // in all possible rotations convertBytesToSyms_QPSK(TXheaderbytes, QPSK_headertab[0], 3); for(int i=1; i<4; i++) rotateQPSKsyms(QPSK_headertab[i-1], QPSK_headertab[i], 12); // create the 8PSK symbol table for the HEADER // in all possible rotations convertBytesToSyms_8PSK(TXheaderbytes, _8PSK_headertab[0], 3); for(int i=1; i<8; i++) rotate8PSKsyms(_8PSK_headertab[i-1], _8PSK_headertab[i], 8); } // packs a payload into an udp data block // the payload has a size of PAYLOADLEN // type ... inserted in the "frame type information" field // status ... specifies first/last frame of a data stream uint8_t *Pack(uint8_t *payload, int type, int status, int *plen) { FRAME frame; // raw frame without fec // polulate the raw frame // make the frame counter if(status & (1<<4)) framecounter = 0; // first block of a stream else framecounter++; // insert frame counter and status bits frame.counter_LSB = framecounter & 0xff; int framecnt_MSB = (framecounter >> 8) & 0x03; // Bit 8+9 of framecounter frame.status = framecnt_MSB << 6; frame.status += ((status & 0x03)<<4); frame.status += (type & 0x0f); // insert the payload memcpy(frame.payload, payload, PAYLOADLEN); // calculate and insert the CRC16 uint16_t crc16 = Crc16_messagecalc(CRC16TX,(uint8_t *)(&frame), CRCSECUREDLEN); frame.crc16_MSB = (uint8_t)(crc16 >> 8); frame.crc16_LSB = (uint8_t)(crc16 & 0xff); // make the final arry for transmission static uint8_t txblock[UDPBLOCKLEN]; // calculate the fec and insert into txblock (leave space for the header) GetFEC((uint8_t *)(&frame), DATABLOCKLEN, txblock+HEADERLEN); // scramble TX_Scramble(txblock+HEADERLEN, FECBLOCKLEN); // scramble all data // insert the header memcpy(txblock,TXheaderbytes,HEADERLEN); /* test pattern * for(int i=0; i>6; // frame counter MSB framenumrx <<= 8; framenumrx += frame.counter_LSB; // frame counter LSB //printf("Frame no.: %d\n",framenumrx); if (lastframenum != framenumrx) rx_status |= 4; lastframenum = framenumrx; if (++lastframenum >= 1024) lastframenum = 0; // 1024 = 2^10 (10 bit frame number) // extract information and build the string for the application // we have 10 Management Byte then the payload follows static uint8_t payload[PAYLOADLEN+10]; payload[0] = frame.status & 0x0f; // frame type payload[1] = (frame.status & 0xc0)>>6; // frame counter MSB payload[2] = frame.counter_LSB; // frame counter LSB payload[3] = (frame.status & 0x30)>>4; // first/last frame marker payload[4] = rx_status; // frame lost information payload[5] = speed >> 8; // measured line speed payload[6] = speed; payload[7] = 0; // free for later use payload[8] = 0; payload[9] = 0; memcpy(payload+10,frame.payload,PAYLOADLEN); return payload; }