rendered paste body// config.c#include "global.h"#include "ctboard.h"#include "serial.h"#include "config.h"#include "loop.h"#include "command.h"#include "rprintf.h"#include <eeprom.h>#include <string.h>// current menu entry:#define MENU_OFF 0#define MENU_BAUD 1#define MENU_ECHO 2#define MENU_RXLE 3#define MENU_TXLE 4#define MENU_EEPROM 5#define MENU_NUM 6// ----- prototypes -----static void saveConfigToEEPROM(void);static byte loadConfigFromEEPROM(void);static void changeMenu(byte up);// ----- local vars -----static byte menuMode = MENU_OFF;// current pos in sniff sequencestatic byte linkSeqPos = 0;// do we need a hardware updatestatic byte needHWUp = 0;// currently in link modestatic byte linked = 0;// map calibration: lower and upper sample valuestatic u16 adcL=0,mapL=0,adcU=10,mapU=10;// ----- CONFIG BYTES -----#define MAX_LINK_START_CMD 8typedef struct { u16 adcMin[2],adcMax[2]; u16 mapMin[2],mapMax[2]; byte baudRate; byte startLinked; byte sniff; byte source; byte rxLineEnd; byte txLineEnd; byte echo; byte linkStartLen; byte linkStartCmd[MAX_LINK_START_CMD]; byte checkSum;} config_t;config_t config = { .adcMin = { 0,0 }, .adcMax = { 0x3ff,0x3ff }, .mapMin = { 0,0 }, .mapMax = { 100,100 }, .baudRate = BAUD_RATE_9600, .startLinked = 0, .sniff = 1, .source = MPLEX_SRC_XPT, .rxLineEnd = LINE_END_CR, .txLineEnd = LINE_END_CRLF, .echo = 1, .linkStartLen = 2, .linkStartCmd = {'l','c'}};// eeprom configconfig_t configEEPROM __attribute__ ((section (".eeprom")));// ---------- remap ADC value ----------u16 remapADC(byte port,u16 value){ u16 adcRange = config.adcMax[port] - config.adcMin[port]; u16 realRange = config.mapMax[port] - config.mapMin[port]; if(value<config.adcMin[port]) return config.mapMin[port]; else if(value>config.adcMax[port]) return config.mapMax[port]; value -= config.adcMin[port]; u32 vl = (u32)value; u32 ar = (u32)adcRange; u32 rr = (u32)realRange; u32 rs = vl * rr / ar; u16 r = (u16)rs; r += config.mapMin[port]; return r;}// ----- calibMapping -----// setup the adc and map range for an ADC port// a linear monotonous mapping from adc to map// given are the two samples (adcL,mapL) and (adcU,mapU)// with adcL < adcU and mapL < mapU#define ADC_MAX 0x03ff#define MAP_MAX 0xffffbyte calibMapping(byte port){ // check parameters if((adcL>=adcU)||(mapL>=mapU)) return EXEC_ERROR; u16 adcDelta = adcU - adcL; u16 mapDelta = mapU - mapL; u32 md = (u32)mapDelta; u32 ad = (u32)adcDelta; u32 ml = (u32)mapL; u32 al = (u32)adcL; // ----- determine ADC range ----- u32 A = al * md; u32 B = ad * ml; u32 pos; // MIN: origin if(A == B) { config.mapMin[port] = 0; config.adcMin[port] = 0; } // MIN: limit ADC range else if(A > B) { pos = B / md; config.mapMin[port] = 0; config.adcMin[port] = (u16)pos; } //MIN: limit MAP range else { pos = A / ad; config.mapMin[port] = ml - (u16)pos; config.adcMin[port] = 0; } A = (MAP_MAX - ml) * ad; B = (ADC_MAX - al) * md; // MAX: both max if(A == B) { config.mapMax[port] = MAP_MAX; config.adcMax[port] = ADC_MAX; } // MAX: limit MAP range else if(A > B) { pos = B / ad; config.mapMax[port] = ml + (u16)pos; config.adcMax[port] = ADC_MAX; } // MAX: limit ADC range else { pos = A / md; config.mapMax[port] = MAP_MAX; config.adcMax[port] = al + (u16)pos; } return EXEC_OK;}// ---------- HW Update & Init ----------byte needHWUpdate(void){ return needHWUp;}void doHWUpdate(void){ needHWUp = 0; setMplex(linked,config.source); setBaud(config.baudRate); ct_beep(1);}void initConfig(){ // load fails... beep and save default if(!loadConfigFromEEPROM()) { ct_beep(3); saveConfigToEEPROM(); } linked = config.startLinked; doHWUpdate();}static void linkStart(void){ needHWUp = 1; linked = 1;}static void linkEnd(void){ needHWUp = 1; linked = 0;}byte isLinked(void){ return linked;}// ----- check link stard cmd -----void checkLinkStartCmd(byte b){ byte found = 0; byte retry = 0; // CRLF mode: start sequence finally found? if(linkSeqPos == config.linkStartLen+1) { if(b == '\n') found = 1; else retry = 1; } // CR, LF mode: check for final char else if(linkSeqPos == config.linkStartLen) { // check for LF,CR,CRLF if(config.rxLineEnd==LINE_END_LF) { if(b == '\n') found = 1; else retry = 1; } else if(config.rxLineEnd==LINE_END_CR) { // CR/CRLF if(b == '\r') found = 1; else retry = 1; } else { // CRLF if(b == '\r') linkSeqPos++; else retry = 1; } } // still in start sequence? else if(b == config.linkStartCmd[linkSeqPos]) linkSeqPos++; else retry = 1; // restart search if(retry) { linkSeqPos = 0; if(b == config.linkStartCmd[0]) linkSeqPos++; } // found sequence start -> enter link mode if(found) linkStart();}byte cmdExit(void){ linkEnd(); return EXEC_QUIT;}// ---------- key handling ---------void handleMenuKeys(byte keys){ // RED: next menu item if(keys & CT_LED_RED) { menuMode++; if(menuMode==MENU_NUM) menuMode=1; } // ORANGE: dec value if(keys & CT_LED_ORANGE) { changeMenu(0); } // YELLOW: inc value if(keys & CT_LED_YELLOW) { changeMenu(1); } // GREEN: leave menu if(keys & CT_LED_GREEN) { menuMode = 0; }}void handleNormalKeys(byte keys){ // RED: enter menu if(keys & CT_LED_RED) { menuMode = 1; } // ORANGE: toggle source if(keys & CT_LED_ORANGE) { if(config.source == MPLEX_SRC_XPT) config.source = MPLEX_SRC_COM; else config.source = MPLEX_SRC_XPT; needHWUp = 1; } // YELLOW: toggle pass/sniff if(keys & CT_LED_YELLOW) { config.sniff = 1-config.sniff; } // GREEN: enter link mode if(keys & CT_LED_GREEN) { linkStart(); }}static void handleLinkKeys(byte keys) { // RED: key command if(keys & CT_LED_RED) { keyCommand(0); } // ORANGE: key command if(keys & CT_LED_ORANGE) { keyCommand(1); } // YELLOW: key command if(keys & CT_LED_YELLOW) { keyCommand(2); } // GREEN: leave link mode if(keys & CT_LED_GREEN) { linkEnd(); }}void handleKeys(byte keys){ if(menuMode!=MENU_OFF) return handleMenuKeys(keys); else if(linked) return handleLinkKeys(keys); else return handleNormalKeys(keys);}// ---------- status ----------static void showStatusOnLCD(void){ byte *str; ct_lcd_clear(); // current connection src if(config.source==MPLEX_SRC_XPT) rprintfStr("XPort "); else rprintfStr("RS232 "); // current connection mode if(linked) rprintfStr("LINK "); else if(config.sniff) rprintfStr("snif "); else rprintfStr("pass "); // baud baud rate switch(config.baudRate) { case BAUD_RATE_9600: str = " 9.6"; break; case BAUD_RATE_19200: str = " 19.2"; break; case BAUD_RATE_38400: str = " 38.4"; break; case BAUD_RATE_57600: str = " 57.6"; break; case BAUD_RATE_115200:str = "115.2"; break; default: str = "?"; break; } rprintfStr(str);}static void showStatusOnLEDs(void) { // RED/ORANGE: connection src if(config.source == MPLEX_SRC_COM) { ct_led_on (CT_LED_RED); ct_led_off(CT_LED_ORANGE); } else { ct_led_off(CT_LED_RED); ct_led_on (CT_LED_ORANGE); } // YELLOW: green led is sniff mode LED if(config.sniff) ct_led_on (CT_LED_YELLOW); else ct_led_off(CT_LED_YELLOW); // GREEN: connection mode if(linked) ct_led_on (CT_LED_GREEN); else ct_led_off(CT_LED_GREEN);} void showStatus(void){ if((menuMode==MENU_OFF)&&(!linked)) showStatusOnLEDs(); showStatusOnLCD();}// ---------- menu control ----------byte isMenuOpen(void){ return menuMode != MENU_OFF;}static void showOnOffOnLCD(byte value){ if(value) rprintfStr("on"); else rprintfStr("off");}static void showLineEndOnLCD(byte value){ if(value==LINE_END_LF) rprintfStr("LF"); else if(value==LINE_END_CR) rprintfStr("CR"); else rprintfStr("CRLF");}static void showMenuOnLCD(void){ ct_lcd_pos(0,1); rprintfChar('@'); switch(menuMode) { default: break; case MENU_BAUD: rprintfStr("baud rate"); break; case MENU_ECHO: rprintfStr("echo char: "); showOnOffOnLCD(config.echo); break; case MENU_RXLE: rprintfStr("rx eol: "); showLineEndOnLCD(config.rxLineEnd); break; case MENU_TXLE: rprintfStr("tx eol: "); showLineEndOnLCD(config.txLineEnd); break; case MENU_EEPROM: rprintfStr("save/load"); break; }}static void showOnOffOnLEDs(byte value){ ct_led_off(CT_LED_ALL); if(value) ct_led_on(CT_LED_GREEN); else ct_led_on(CT_LED_RED);}static void showValueOnLEDs(byte value){ ct_led_off(CT_LED_ALL); if(value==0) ct_led_on(CT_LED_RED); else if(value==1) ct_led_on(CT_LED_ORANGE); else if(value==2) ct_led_on(CT_LED_YELLOW); else ct_led_on(CT_LED_GREEN);}static void showMenuOnLEDs(void){ switch(menuMode) { default: break; case MENU_BAUD: ct_led_bits(config.baudRate+1); break; case MENU_ECHO: showOnOffOnLEDs(config.echo); break; case MENU_RXLE: showValueOnLEDs(config.rxLineEnd); break; case MENU_TXLE: showValueOnLEDs(config.txLineEnd); break; case MENU_EEPROM: ct_led_off(CT_LED_ALL); break; }}void showMenu(void){ showMenuOnLCD(); showMenuOnLEDs();}static void changeMenu(byte up){ switch(menuMode) { default: break; case MENU_BAUD: if(up) { if(config.baudRate<BAUD_RATE_LAST) config.baudRate++; } else { if(config.baudRate>0) config.baudRate--; } needHWUp = 1; break; case MENU_ECHO: config.echo = up; break; case MENU_RXLE: if(up) { if(config.rxLineEnd<LINE_END_LAST) config.rxLineEnd++; } else { if(config.rxLineEnd>0) config.rxLineEnd--; } break; case MENU_TXLE: if(up) { if(config.txLineEnd<LINE_END_LAST) config.txLineEnd++; } else { if(config.txLineEnd>0) config.txLineEnd--; } break; case MENU_EEPROM: if(up) { if(!loadConfigFromEEPROM()) ct_beep(3); else ct_beep(1); } else { saveConfigToEEPROM(); ct_beep(1); } break; }}// ---------- command ----------byte cmdConfig(byte *cmd){ byte port; u16 value,value2; switch(cmd[0]) { // load/save case 'S': // cs - save config to EEPROM saveConfigToEEPROM(); break; case 'L': // cl - load config from EEPROM if(!loadConfigFromEEPROM()) return EXEC_ERROR; break; // settings case 'e': // ce0 ce1 - set echo mode, ce - print echo mode if(cmd[1]=='0') config.echo = 0; else if(cmd[1]=='1') config.echo = 1; else if(cmd[1]!=0) return EXEC_ERROR; rprintfChar('0'+config.echo); return EXEC_OK | EXEC_RESULT; case 'r': // rx eol: 0=LF 1=CR 2=CR+LF if(parseNibble(cmd[1],&port)) { if(port>LINE_END_LAST) return EXEC_ERROR; config.rxLineEnd = port; } rprintfu04(config.rxLineEnd); return EXEC_OK | EXEC_RESULT; case 't': // tx eol: 0=LF 1=CR 2=CR+LF if(parseNibble(cmd[1],&port)) { if(port>LINE_END_LAST) return EXEC_ERROR; config.txLineEnd = port; } rprintfu04(config.txLineEnd); return EXEC_OK | EXEC_RESULT; case 'b': // set baud rate if(parseNibble(cmd[1],&port)) { if(port>BAUD_RATE_LAST) return EXEC_ERROR; config.baudRate = port; } rprintfu04(config.baudRate); return EXEC_OK | EXEC_RESULT; case 'k': // set key word if(cmd[1]!=0) { cmd++; byte len = 0; while(cmd[len]!=0) { config.linkStartCmd[len] = cmd[len]; len++; } config.linkStartLen = len; } rprintfStrLen(config.linkStartCmd,0,config.linkStartLen); return EXEC_OK | EXEC_RESULT; case 's': // set link source: 0=COM 1=LAN if(parseNibble(cmd[1],&port)) { if(port>1) return EXEC_ERROR; config.source = port; } rprintfu04(config.source); return EXEC_OK | EXEC_RESULT; case 'l': // set link state: 1=link 0=sniff/pass-through if(parseNibble(cmd[1],&port)) { if(port>1) return EXEC_ERROR; config.startLinked = port; } rprintfu04(config.startLinked); return EXEC_OK | EXEC_RESULT; case 'i': // set sniff mode: 1=sniff 0=pass-through if(parseNibble(cmd[1],&port)) { if(port>1) return EXEC_ERROR; config.sniff = port; } rprintfu04(config.sniff); return EXEC_OK | EXEC_RESULT; case 'm': // real range mapping if(cmd[1]=='r') { if(cmd[2]=='l') { // lower sample value = adcL; value2 = mapL; } else if(cmd[2]=='u') { // upper sample value = adcU; value2 = mapU; } else { if(!parseNibble(cmd[2],&port)) return EXEC_ERROR; if(port>1) return EXEC_ERROR; if(cmd[3]=='a') { // get adc range value = config.adcMin[port]; value2 = config.adcMax[port]; } else if(cmd[3]=='m') { // get map range value = config.mapMin[port]; value2 = config.mapMax[port]; } else return EXEC_ERROR; } } else if(cmd[1]=='w') { byte pos = 4; if((cmd[2]=='l')||(cmd[2]=='u')) pos = 3; if(!parseWord(&cmd[pos],&value)) return EXEC_ERROR; if(!parseWord(&cmd[pos+5],&value2)) return EXEC_ERROR; if(cmd[2]=='l') { // lower sample adcL = value; mapL = value2; } else if(cmd[2]=='u') { // upper sample adcU = value; mapU = value2; } else { if(!parseNibble(cmd[2],&port)) return EXEC_ERROR; if(port>1) return EXEC_ERROR; if(cmd[3]=='a') { // set adc range config.adcMin[port] = value; config.adcMax[port] = value2; } else if(cmd[3]=='m') { // set map range config.mapMin[port] = value; config.mapMax[port] = value2; } else return EXEC_ERROR; } } else if(cmd[1]=='c') { // calibrate with lower and upper sample if(!parseNibble(cmd[2],&port)) return EXEC_ERROR; if(port>1) return EXEC_ERROR; return calibMapping(port); } else return EXEC_ERROR; rprintfu16(value); rprintfChar(' '); rprintfu16(value2); return EXEC_OK | EXEC_RESULT; default: return EXEC_ERROR; } return EXEC_OK;}// ---------- query config ----------byte isStartLinked(void){ return config.startLinked;}byte isSniff(void){ return config.sniff;}byte doEcho(void){ return config.echo;}void sendEOL(void){ sendLineEnd(config.txLineEnd);}void sendLineEOL(const byte *line){ sendLine(config.txLineEnd,line);}byte isEOL(byte b){ if(b=='\r') { if(config.rxLineEnd==LINE_END_CR) return 1; else if(config.rxLineEnd==LINE_END_CRLF) return 2; else return 0; } else if(b=='\n') { if(config.rxLineEnd!=LINE_END_CR) return 1; else return 0; } else return 0;}// ---------- eeprom ----------void saveConfigToEEPROM(void){ // calc check sum config.checkSum = 0; byte *adr = (byte *)&config; byte sum = 0; for(byte i=0;i<sizeof(config_t);i++) sum += adr[i]; config.checkSum = sum; eeprom_write_block(&config,&configEEPROM,sizeof(config_t));}byte loadConfigFromEEPROM(void){ config_t tempConfig; eeprom_read_block(&tempConfig,&configEEPROM,sizeof(config_t)); byte tempSum = tempConfig.checkSum; tempConfig.checkSum = 0; byte sum = 0; byte *adr = (byte *)&tempConfig; for(byte i=0;i<sizeof(config_t);i++) sum += adr[i]; // check sum ok if(sum == tempSum) { memcpy(&config,&tempConfig,sizeof(config_t)); return 1; } return 0;}