Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.
Diff: pccomms/handlers/mode1.c
- Revision:
- 0:0a841b89d614
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pccomms/handlers/mode1.c Mon Oct 11 10:34:55 2010 +0000 @@ -0,0 +1,142 @@ +/**************************************************************************** + * Copyright 2010 Andy Kirkham, Stellar Technologies Ltd + * + * This file is part of the Satellite Observers Workbench (SOWB). + * + * SOWB 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 3 of the License, or + * (at your option) any later version. + * + * SOWB 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 SOWB. If not, see <http://www.gnu.org/licenses/>. + * + * $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $ + * + ***************************************************************************/ + +/* +MODE 1 Packet handler. + +This mode is used by the Host to send a file containing all the TLEs that +SOWB needs to aquire satellites. The base packet payload itself conatins +a sub packet as defined below. Note, we assign a number of flash pages to +the TLE file. Each flash page is 256bytes in size. So, the host sends the +file in 256byte blocks. The sub-packet header defines the block being sent. +We add to this block the flash base page and write the 256byte sub-packet +payload into the flash device. Note, TLE files are ascii characters so the +sub-packet payload is ASCII itself and doesn't require any conversions. + +Subp-acket format <BBBBCF>......... +Where:- + < is the "start of packet header" character. + BBBB is a hex string representation of the uint16_t 256 char block. + C is a two's complement checksum of the header from < to > inclusive. + F is a char flag. Normally zero. + > is the "end of packet header" character. + .... is the packet payload, 256 bytes in length. + +*/ + +#include "sowb.h" +#include "user.h" +#include "utils.h" +#include "flash.h" +#include "pccomms.h" + +#define FLASH_BASE_TLE_FILE 10 + +/* Error flags to send back on failure. */ +#define FLAG_BAD_CHECKSUM '1' +#define FLAG_INVALID_LENGTH '2' + +/* Base packet payload to sub-packet header definition. */ +typedef struct _pccomms_mode1_header { + char lead_char; + char block[4]; + char csum; + char flag; + char trail_char; +} PCCOMMS_MODE1_HEADER; + +/* Base packet payload to sub-packet overall definition. */ +typedef struct _pccomms_mode1 { + PCCOMMS_MODE1_HEADER header; + char payload[256]; +} PCCOMMS_MODE1; + + +/** pccomms_mode1_failed + * + * Used to send back a failed packet with a flag "reason for failure". + * + * @param BASE_PACKET_A *a The original ASCII version of the packet header. + * @param char flag The char flag to insert. + */ +void pccomms_mode1_failed(BASE_PACKET_A *a, char flag) { + BASE_PACKET_A temp; + char *p; + int i; + + memcpy((char *)&temp, (char *)a, sizeof(BASE_PACKET_A)); + temp.flag = flag; + temp.csum = 0; + temp.csum = strcsuml((char *)&temp, sizeof(BASE_PACKET_A)); + for (p = (char *)&temp, i = 0; i < sizeof(BASE_PACKET_A); i++) { + Uart3_putc((char)p[i]); + } +} + +/** pccomms_mode1_handler + * + * The packet handler for MODE 1. + * + * @param BASE_PACKET_B *b + * @param BASE_PACKET_A *a + * @return int + */ +int pccomms_mode1_handler(BASE_PACKET_B *b, BASE_PACKET_A *a) { + PCCOMMS_MODE1 data; + char *p; + int page, c, i; + + /* Sanity check, should never fail, should really assert() */ + if (b->mode != 1) return PCCOMMS_PACKET_REJECTED; + + /* Sanity check, should never fail, should really assert() */ + if (b->length != sizeof(PCCOMMS_MODE1)) return PCCOMMS_PACKET_REJECTED; + + /* Copy the base packet payload into our internal data structure. */ + for(p = (char *)&data, i = 0; i < sizeof(PCCOMMS_MODE1); i++) { + c = Uart3_getc(0); + if (c != -1) p[i] = (char)c; + else { + /* This shouldn't happen as once the IRQ system has detected the + end of the packet it no longer inserts serial chars into the + buffer. So another sanity check really. Unless the Host did + in fact screw up somewhere. */ + pccomms_mode1_failed(a, FLAG_INVALID_LENGTH); + return PCCOMMS_PACKET_REJECTED; + } + } + + /* Run a checksum check. On failure, send back the Host's packet with "flag" set to "bad checksum". */ + if (strsuml((char *)&data, sizeof(PCCOMMS_MODE1)) != 0) { + pccomms_mode1_failed(a, FLAG_BAD_CHECKSUM); + return PCCOMMS_PACKET_REJECTED; + } + + /* Get the block header and add the flash page offset. */ + page = (int)hex2bin(data.header.block, 4) + FLASH_BASE_TLE_FILE; + + /* Assuming we programmed the flash device ok, return packet accepted. */ + flash_page_write(page, data.payload); + while(flash_write_in_progress()) user_call_process(); + return PCCOMMS_PACKET_ACCEPTED; +} +