void ev3rt_load_configuration() { /** * Create '/ev3rt/etc/' */ f_mkdir("/ev3rt"); f_mkdir("/ev3rt/etc"); static char localname[100]; ini_gets("Bluetooth", "LocalName", "Mindstorms EV3", localname, 100, CFG_INI_FILE); ini_puts("Bluetooth", "LocalName", localname, CFG_INI_FILE); ev3rt_bluetooth_local_name = localname; static char pincode[17]; ini_gets("Bluetooth", "PinCode", "0000", pincode, 17, CFG_INI_FILE); ini_puts("Bluetooth", "PinCode", pincode, CFG_INI_FILE); ev3rt_bluetooth_pin_code = pincode; static bool_t disable_port_1; disable_port_1 = ini_getbool("Sensors", "DisablePort1", false, CFG_INI_FILE); ini_putl("Sensors", "DisablePort1", disable_port_1, CFG_INI_FILE); ev3rt_sensor_port_1_disabled = &disable_port_1; }
void ev3rt_load_configuration() { /** * Create '/ev3rt/etc/' */ f_mkdir("/ev3rt"); f_mkdir("/ev3rt/etc"); char sio_default_port[5]; ini_gets("Debug", "DefaultPort", NULL, sio_default_port, 5, CFG_INI_FILE); if (!strcasecmp("UART", sio_default_port)) { SIO_PORT_DEFAULT = SIO_PORT_UART; } else if (!strcasecmp("BT", sio_default_port)) { SIO_PORT_DEFAULT = SIO_PORT_BT; } else { // Use LCD by default SIO_PORT_DEFAULT = SIO_PORT_LCD; ini_puts("Debug", "DefaultPort", "LCD", CFG_INI_FILE); } static bool_t low_battery_warning; low_battery_warning = ini_getbool("Debug", "LowBatteryWarning", true, CFG_INI_FILE); ini_putl("Debug", "LowBatteryWarning", low_battery_warning, CFG_INI_FILE); ev3rt_low_battery_warning = &low_battery_warning; static bool_t disable_bluetooth; disable_bluetooth = ini_getbool("Bluetooth", "TurnOff", false, CFG_INI_FILE); ini_putl("Bluetooth", "TurnOff", disable_bluetooth, CFG_INI_FILE); ev3rt_bluetooth_disabled = &disable_bluetooth; static char localname[100]; ini_gets("Bluetooth", "LocalName", "Mindstorms EV3", localname, 100, CFG_INI_FILE); ini_puts("Bluetooth", "LocalName", localname, CFG_INI_FILE); ev3rt_bluetooth_local_name = localname; static char pincode[17]; ini_gets("Bluetooth", "PinCode", "0000", pincode, 17, CFG_INI_FILE); ini_puts("Bluetooth", "PinCode", pincode, CFG_INI_FILE); ev3rt_bluetooth_pin_code = pincode; static int disable_pan; #if !defined(BUILD_LOADER) // TODO: Bluetooth PAN is only supported by loader currently disable_pan = 1; #else disable_pan = ini_getbool("Bluetooth", "DisablePAN", false, CFG_INI_FILE); ini_putl("Bluetooth", "DisablePAN", disable_pan, CFG_INI_FILE); #endif ev3rt_bluetooth_pan_disabled = &disable_pan; // TODO: check valid IP address static char ip_address[16]; ini_gets("Bluetooth", "IPAddress", "10.0.10.1", ip_address, 17, CFG_INI_FILE); ini_puts("Bluetooth", "IPAddress", ip_address, CFG_INI_FILE); ev3rt_bluetooth_ip_address = ip_address; static bool_t disable_port_1; disable_port_1 = ini_getbool("Sensors", "DisablePort1", false, CFG_INI_FILE); ini_putl("Sensors", "DisablePort1", disable_port_1, CFG_INI_FILE); if (SIO_PORT_DEFAULT == SIO_PORT_UART) disable_port_1 = true; DEBUG_UART = disable_port_1 ? 0 : 4; ev3rt_sensor_port_1_disabled = &disable_port_1; static bool_t auto_term_app; auto_term_app = ini_getbool("USB", "AutoTerminateApp", true, CFG_INI_FILE); ini_putl("USB", "AutoTerminateApp", auto_term_app, CFG_INI_FILE); ev3rt_usb_auto_terminate_app = &auto_term_app; }
static void write_config_value_int(const char *filename, const char *section, const char *key, const long value) { if (ini_putl(section, key, value, filename) != 1) { LOG_ERR("Settings", "Unable to save config value: %lu.", value); } }
/* Command interpreter for VBIT, The leading SO and trailing carriage return are already removed The X command returns 2 Other good commands return 0 and bad commands return 1. Also after a P command if selecting a single page fails, the page is created and 8 is the return code */ static int vbit_command(char *Line) { static uint8_t firstLine=true; static uint16_t SRAMAddress; // The address pointer into the FIFO serial ram unsigned char rwmode; unsigned char returncode=0; int pagecount; uint8_t directorySteps; int8_t sign; // 1=plus -1=minus char ch; unsigned char valid; long n; unsigned char i; char str[80]; char *ptr; char *dest; str[0]='O'; str[1]='K'; str[2]='\0'; // char data[80]; // This stuff is to do with locating pages in the display list (Directory command) // (also shared with ee/ea command for uploading pages) NODEPTR np; DISPLAYNODE node; PAGEINDEXRECORD ixRec; uint16_t charcount; uint8_t res; DWORD fileptr; // Used to save the file pointer to the body of the ttx file PAGE page; // ee/ea specific variable static DWORD StartOfPage; DWORD EndOfPage; // Records the start and end of the new page PAGEINDEXRECORD pageindex; uint16_t ix; char packet[45]; static uint8_t row; // Teletext row counter for JA/JZ/JW command // tba // Read, Update or not switch (Line[2]) { case 'R' : rwmode=CMD_MODE_READ; break; case 'U' : rwmode=CMD_MODE_WRITE;break; default: rwmode=CMD_MODE_NONE; } /* Is there actually any data */ if (*Line==0) returncode=1; else switch (Line[1]) { case 'b': // Dump the current page dumpPage(); break; case 'C': // Create magazine lists // TODO: Kill video // TODO: C<pages to pre-allocate> // this would speed up the process immensely // It only needs to be approximate as FatFS will extend the file as needed. cli(); pagecount=300; for (i=1;i<=1;i++) // TODO: Do we need more lists? Probably can find a way around it. SDCreateLists(i,pagecount); sei(); break; case 'D': // Directory - D[<F|L>][<+|->][<n>] // Where F=first, L=Last, +=next, -=prev, n=number of pages to step (default 1) //xprintf(PSTR("D Command needs to be written")); // It would probably be a good idea to save the seek pointer // do the reading required // and then reset it. This would save memory. // If the ee command is active, don't allow D to mess the page variable. if (firstLine) { returncode=1; // ee command is busy. break; } directorySteps=0; sign=1; for (i=2;Line[i];i++) { ch=Line[i]; // xprintf(PSTR("Processing Line[%d]=%c\n\r"),i,Line[i]); switch (ch) { case 'F' : ; // Set the first item DirectoryFirst(); break; case 'L' : ; // Set the last item DirectoryLast(); break; case '+' : ; // Next item directorySteps=1; sign=1; // xprintf(PSTR("D+ not implemented")); break; case '-' : ; // Previous item directorySteps=1; sign=-1; // xprintf(PSTR("D- not implemented")); break; default: // Number of steps (TODO: Extend to a generic decimal) if (ch>='0' && ch <='9') { directorySteps=ch; } Line[i]=0;// Force this to be the last option break; // Break because this must be the last option } // Find the page if (LocatePage(directorySteps*sign)==NULLPTR) { // Probably want to set an error value as we failed to iterate // But I don't think that we return anything different. // We rely on TED scheduler to remember the count returned by the P command and NOT overrun } // TODO: Work out what to do with the rest of the parameters np=GetNodePtr(¤tPage); // TODO: Handle sub pages GetNode(&node,np); // Instead treat the page like a single page f_lseek(&listFIL,(node.pageindex)*sizeof(PAGEINDEXRECORD)); // Seek the page index f_read(&listFIL,&ixRec,sizeof(PAGEINDEXRECORD),&charcount); // and read it // Now seek the actual page that we are referencing res=f_open(&PageF,"pages.all",FA_READ); // Now look for the relevant page f_lseek(&PageF,ixRec.seekptr); // Seek the actual page // Now we have the page, we need to seek through it to get // the data while (PageF.fptr<(ixRec.seekptr+ixRec.pagesize)) { fileptr=PageF.fptr; // Save the file pointer in case we found "OL" f_gets(str,sizeof(str),&PageF); if (str[0]=='O' && str[1]=='L') { f_lseek (&PageF, fileptr); // Step back to the OL line break; } if (ParseLine(&page, str)) { xprintf(PSTR("[insert]file error handler needed:%s\n"),str); // At this point we are stuffed. f_close(&PageF); returncode=1; break; // what else should we do if we get here? } } // bb mpp qq cc tttt ssss n xxxxxxx // Leading zeros rely on PRINTF_LIB_FLOAT in makefile!!! sprintf_P(str,PSTR("%02X %03X %02d %02X %04X 0000 %1d 00000000"), 3, // seconds (hex) 0x100+(currentPage/2), // mpp page.subpage, // ss page.control, // S page.time, // Cycle time (secs) (currentPage>>8)+1); // Mag f_close(&PageF); } // str[0]=0; // might return the directory paramaters here break; case 'E' : // EO, ES, EN, EP, EL, EM - examine switch (Line[2]) { case 'M': // EM - Return Miscellaneous flags { // These are BFLSU. The code below is not correct n = ini_getl("service", "serialmode", 0, inifile); if (n) xputs(PSTR("20")); else xputs(PSTR("00")); break; } break; default: returncode=1; case 'O': // EO - Output dataline actions set by QO // 18 characters on a line, but odd ignores last action n = ini_gets("service", "outputodd", "111Q2233P445566778", str, sizearray(str), inifile); n = ini_gets("service", "outputeven", "111Q2233P445566778", str, sizearray(str), inifile); xprintf(PSTR("%s"),str); break; } break; // E commands case 'e' : // ea or ee : Upload page(s). // These pages add the lines at the end of the page file, and patch the index. // Warning. "page" is shared with the directory command // directory calls are blocked until you do ee. switch (Line[2]) { case 'a' : // Add a page, line at a time. passBackspace=true; if (firstLine) { firstLine=false; ClearPage(&page); // Clear out our Page object res=f_open(&PageF,"pages.all",FA_READ| FA_WRITE); // Ready to write // TODO: check the value of res //xprintf(PSTR("Size of pages.all=%ul\n\r"),PageF.fsize); /* Move to end of pages.all to append data */ res=f_lseek(&PageF, PageF.fsize); //xprintf(PSTR("lseek res=%d\n\r"),res); StartOfPage=PageF.fptr; // We need the Start Of Page for the index } // uh fellows, Although we get \r => Ctrl-P, we need to map it to 0x8d which is the file format. for (ptr=&Line[4];*ptr;ptr++) if (*ptr==0x10) *ptr=0x8d; f_puts(&Line[4],&PageF); // The rest of the line is the file contents f_putc('\n',&PageF); // Add the LF that the interpreter strips out xprintf(PSTR("Now writing:%s\n\r"),&Line[4]); // Don't unencode the line, pages.all should follow MRG \r => ctrl-P substitutions // Probably can ignore Viewdata escapes. // Write the rest of the line to pages.all // Parse the line so we have all the page details so we know where to put it in the array/node if (ParseLine(&page, &Line[4])) { xprintf(PSTR("Your page sucks. Unable to parse this nonsense\n\r")); returncode=1; // failed // TODO: implement the break // break; } break; // a case 'e' : // We finished. End the update passBackspace=false; EndOfPage=PageF.fptr; f_close(&PageF); // We are done with pages.all // We need to refresh the transmission file object so close and re-open it f_close(&pagefileFIL); res=f_open(&pagefileFIL,"pages.all",FA_READ); // Only need to open this once! // Or are we all done? We need to write the page to Pmpp.TTI so that we can rebuild the index later pageindex.seekptr=StartOfPage; pageindex.pagesize=(uint16_t)(EndOfPage-StartOfPage); // Warning! 16 bit file size limits to about 50 subpages. xprintf(PSTR("seek %ld size %d \n\r"),pageindex.seekptr,pageindex.pagesize); // 1: Append pages.idx with the file start/end (append pageindex) f_close(&listFIL); // TODO: Perhaps we should check that this is actually opened first? res=f_open(&listFIL,"pages.idx",FA_READ| FA_WRITE); // Ready to write // TODO: check the value of res ix=listFIL.fsize; // This is the address in the file res=f_lseek(&listFIL, ix); // Locate the end of the file // Now append the page index f_write(&listFIL,&(pageindex.seekptr),4,&charcount); // 4 byte seek pointer f_write(&listFIL,&(pageindex.pagesize),2,&charcount); // 2 byte file size // Now restore the file to the previous opened readonly state f_close(&listFIL); res=f_open(&listFIL,"pages.idx",FA_READ); // 2: Add the page to the page array. (Or we could rebuild just by doing a restart) ix=ix/sizeof(pageindex); xprintf(PSTR("New page mag=%d page=%02X --> added at ix=%d\n\r"),page.mag,page.page,ix); LinkPage(page.mag, page.page, page.subcode, ix); // TODO: // 3: Add the page to the node list. (ditto) // TODO: firstLine=true; // and reset ready for the next file break; // e default: str[0]=0; returncode=1; } break; // e commands case 'G': /* G - Packet 8/30 format 1 [p830f1]*/ if (rwmode==CMD_MODE_NONE) { str[0]=0; returncode=1; break; } /* C, L N, T, D */ switch (Line[3]) { case 'C' : /* Code. 1=format 1 */ //xputs(PSTR("GUC command not implemented. Why would we need it\n")); // It should always default to 0 /** Where is the initial page done? The code below is wrong */ //SetInitialPage(pkt830,str1,str2); // nb. Hard coded to 100 break; case 'D' : /* up to 20 characters label*/ if (rwmode==CMD_MODE_READ) { n = ini_gets("p830f1", "label", "VBITFax ", str, sizearray(str), inifile); xprintf(PSTR("%s"),str); } if (rwmode==CMD_MODE_WRITE) { n = ini_puts("p830f1", "label", &Line[4], inifile); SetStatusLabel(pkt830,&Line[4]); } break; case 'L' : /* Link */ xputs(PSTR("GUL command\n")); /* Alrighty. The MAG is already in the MRAG. All we actually need is ppssss where pp=hex page number and ssss=hex subcode */ n = ini_gets("p830f1", "initialpage", "003F7F", str, MAXSTR, inifile); break; case 'N' : /* Net IC */ if (rwmode==CMD_MODE_READ) { n = ini_gets("p830f1", "nic", "fa6f", str, sizearray(str), inifile); xprintf(PSTR("%s"),str); } if (rwmode==CMD_MODE_WRITE) { n = ini_puts("p830f1", "nic", &Line[4], inifile); SetNIC1(pkt830,&Line[4]); } break; case 'T' : /* Time */ xputs(PSTR("GUT command\n")); i2c_init(); break; default: str[0]=0; returncode=1; } break; case 'H': // H or HO. Set header if (Line[3]=='\0' || Line[5]=='\0') // Don't get confused by checksums { strcpy_P(str,PSTR(" ")); strncat(str,g_Header,32); // Just readback the header. TODO. Get the correct length str[40]=0; } else { strncpy(g_Header,&Line[9],32); // accept new header //g_Header[32]=0; // Make sure it is capped n = ini_puts("service", "header", g_Header, inifile); // Save this value back to the INI file. } break; case 'I': // III or I2 // I20xnnmm if (Line[2]=='2') // SAA7113 I2C. value. 0xnnmm where nn=address mm=value to write { strcpy_P(str,PSTR("Setting SAA7113 I2C register\n")); ptr=&Line[3]; xatoi(&ptr,&n); xprintf(PSTR("Blah=%04X\n"),n); i2c_SetRegister((n>>8)&0xff,n&0xff); xprintf(PSTR("Done\n")); } break; case 'J' : // J<h>,DATA - Send a packet to SRAM address // Probably want a whole family of J commands. // JA<h> - Set the address pointer to SRAM page <h> where <h> is 0..d // JW<data> - Write a complete 45 byte packet to the current address and increment // JR<data> - Read back the next block of data and increment the pointer. // [JT<h> - Retransmit page <h> immediately. (can't work. You must Tx the parent page) ] // JT<mpp> - Transmit page <mpp> immediately. (probably need to set a flag in the magazine stream // to insert the page in the next transmission slot switch (Line[2]) { case 'A': // eg. JA,0 - Set to the start of //xprintf(PSTR("JA set SRAM address (page level)\n")); Line[2]='0';Line[3]='x'; ptr=&Line[2]; xatoi(&ptr,&n); //xprintf(PSTR("JA page=%X SRAMPAGECOUNT=%X SRAMPAGEBASE=%X\n"),n,SRAMPAGECOUNT,SRAMPAGEBASE); if (n>=SRAMPAGECOUNT) // Make sure the page is in range returncode=1; else { n=SRAMPAGEBASE+n*SRAMPAGESIZE; // This is the actual address //xprintf(PSTR("JA address=%04X\n"),n); SRAMAddress=n; //row=1; } // We should now fill the packet with some instructions on how to use it! // Set the SRAM page address 0..e. There are 14 pages // Coarse address setting // For the lulz, JZ gives random access down to byte level break; case 'Z': // Jay-Z, geddit?, JZ<hex addr 16 bit> Line[2]='0';Line[3]='x'; ptr=&Line[2]; xatoi(&ptr,&n); //xprintf(PSTR("JZ set SRAM address (byte level)\n")); //xprintf(PSTR("JZ page=%04X\n"),n); // Set the SRAM page address at byte level. Needs an actual 16 bit address // where only 15 bits are used. // For finer control than the JA command. // For the lulz and ability to plonk stuff using random access. SRAMAddress=n; break; case 'W': // JW,<row>,data - Write a packet to the SRAM page buffer //xprintf(PSTR("JW Write SRAM data\n")); ptr=&Line[3]; while (*ptr>=' ' && !isdigit(*ptr)) ptr++; // Seek the row value row=atoi(ptr); if (!row) // Row address must be greater than 0 { returncode=1; break; } while (isdigit(*ptr) || *ptr==',') ptr++; // Seek the comma after row // If the fifo is transmitting, we must wait here for (i=0;FIFOBusy;i++); // Can this break if the video source has stopped? We may want to timeout on this! // xprintf(PSTR("JW addr=%d\n"),row); // Write a single packet // Not sure how we are going to map control codes but probably the same as OL // Write the packet that we are going to decode into @SRAMAddress // TODO: Check the row number to see we don't have a buffer overrun // Load and decode the packet // Replace this with a section that reads a line of data from USB // For the first attempt, I'll just copy the rest of the command line // I think it is null terminated? Hmm or \r // JW,<rest of command line> PORTC.OUT&=~VBIT_SEL; // Set the mux to MPU so that we are in control for (i=0;i<45;i++)packet[i]=0; WritePrefix(packet, 5, row); // This prefix gets replaced later packet[3]=row; // The row gets encoded just before writing to FIFO //row++; // MRG line format is bit 8 set if it is a control code < ' ' for (int i=5;i<45 && *ptr && *ptr!='\r';i++) { packet[i]=*ptr++ & 0x7f; } // ** find the address of the row ** n=SRAMAddress+(row-1)*PACKETSIZE; SetSerialRamAddress(SPIRAM_WRITE, n); //xprintf(PSTR("JW write address=%04X\n"),n); //SRAMAddress+=PACKETSIZE; WriteSerialRam(packet,45); DeselectSerialRam(); break; case 'R': xprintf(PSTR("JR Read back SRAM data\n")); // Read back a single packet (translated back into OL format) break; case 'T': xprintf(PSTR("JT Transmit mpp\n")); // Set a flag to transmit the selected page ASAP. break; default: returncode=1; } break; case 'L': // L<nn>,<line data> // We don't use L in vbit. Because it would require RAM buffering or more file writing, // instead we use the e command which writes the file directly. xprintf(PSTR("L command not implemented. Use 'e'\n")); str[0]=0; returncode=1; break; case 'M': // MD - Delete all the pages selected by the last P command. xprintf(PSTR("Delete...\n")); // Iterate down all the pages // Traverse down subpages and release nodes // Go into the pages index and null out the entries in pages.idx break; case 'O': /* O - Opt out. Example: O1c*/ /* Two digit hex number. Only 6 bits are used so the valid range is 0..3f */ ptr=&Line[0]; Line[0]='0';Line[1]='x'; xatoi(&ptr,&n); OptRelays=n & 0x3f; break; case 'P': // P<mppss>. An invalid character will set null. P without parameters will return the current value ptr=&Line[2]; if (!*ptr) { sprintf_P(str,PSTR("%s\n\r"),pageFilter); break; } dest=pageFilter; for (i=0;i<5;i++) { ch=*ptr++; if (ch=='*') valid=1; else { switch (i) { case 0 : // M valid=(ch>'0' && ch<'9' );break; case 1 :; // PP case 2 : valid=((ch>='0' && ch<='9') || (ch>='A' && ch<='F'));break; case 3 :; // SS case 4 : valid=(ch>='0' && ch<='9');break; } } if (valid) *dest++ = ch; else { dest[0]=0; break; } } *dest=0; // terminate the string // TODO: Find out how many pages are in this page range pagecount=FindPageCount(); if (pagecount<0) { pagecount=1; returncode=8; // TODO: At this point we must create the page, as we are about to receive the contents. xprintf(PSTR("Page has been created. Please send some data to fill the page\n\r")); } sprintf_P(str,PSTR("%04d"),pagecount); // Where nnn is the number of pages in this filter. 099 is a filler ack and checksum // str[0]=0; break; case 'Q' : // QO, QM if (Line[2]=='M') // QMnn { ptr=&Line[3]; xatoi(&ptr,&n); xprintf(PSTR("QM command, n=%d\n"),n); n = ini_putl("service", "serialmode", n, inifile); // And at this point put it into the vbi configuration // vbi_mode_serial=0 or CTRL_C11_MAGAZINESERIAL_bm /** TBA. This setting needs to be in the VBI section if (n) vbi_mode_serial=0; else vbi_mode_serial=CTRL_C11_MAGAZINESERIAL_bm; */ break; } // QO sets both odd and even lines // QD only sets the odd. if (Line[2]=='O' || Line[2]=='D') // QO[18 characters <P|Q|1..8|F>]. QD is the odd line and has 18 lines { int i; char ch; ptr=&Line[3]; xputc('0'); // Validate it. for (i=0;i<18;i++) { ch=*ptr++; switch (ch) { case '1':;case'2':;case'3':;case'4':;case'5':;case'6':;case'7':;case'8':;case'I':; case'F':; case'P':; case'Q':; case'Z':; break; default: returncode=1; } g_OutputActions[0][i]=ch; // odd field if (Line[2]=='O') g_OutputActions[1][i]=ch; // even field (QO only) } *ptr=0; if (returncode) break; n = ini_puts("service", "outputodd", &Line[3], inifile); if (Line[2]=='O') n = ini_puts("service", "outputeven", &Line[3], inifile); // QO only break; } returncode=1; break; // We could probably use the S command to encapsulate Newfor. We aren't going to be setting the page status much. case 'S' : ; // Newfor. This should be a Newfor command. Hmm, but how to escape SO and SI? // Work out how to escape data. The parity and reserved characters will break the CI break; case 'T': // T <hhmmss> (this syntax was superceded by GUT and GUt) // testIni(); // test3(); // test2(); // UTC is the time of day in seconds Line[8]=0; ptr=&(Line[2]); UTC=0; // Maybe save this. We need to revert if it fails. for (i=2;i<8;i++) { // First multiply according to which digit switch (i) { case 3:; case 5:; case 7: UTC*=10;break; case 4:; case 6: UTC*=6;break; // (already *10!) } ch=*(ptr++)-'0'; UTC+=ch; } // xprintf(PSTR("UTC=%d\n\r"),UTC); // This upsets the protocol! /** UTC=Line[7]-'0'; // s units UTC=UTC+(Line[6]-'0')*10; // s tens UTC=UTC+(Line[5]-'0')*60; // m units UTC=UTC+(Line[4]-'0')*60*10; // m tens UTC=UTC+(Line[3]-'0')*60*60; // h units UTC=UTC+(Line[2]-'0')*60*60*10; // h tens */ // strcpy_P(str,PSTR("OK\n")); str[0]=0; break; case 'U': // TEST Init830F1(); break; case 'V': // Communication settings. 2 hex chars (bit=(on/off) 7=Viewdata/Text 1=CRLF/CR 0=Echo/Silent // VBIT seems a bit fussy. When using TED Scheduler it is best to sat V00 pagecount=sscanf(&(Line[2]),"%2X",&i); // xprintf(PSTR("sscanf returns %d. Parameter is %X0\n\r"),pagecount,i); if (pagecount>0) { echoMode=i; // Yes, it was OK // TODO: Save the result in the INI } else returncode=1; // No, it failed break; case 'W': // TEST Ad-tec opt outs // W14 - Send a mode 14 opt out // We want to be able to test various ATP950 modes. // read the parameter ptr=&Line[2]; xatoi(&ptr,&n); OptOutMode=n; xprintf(PSTR("W=%04X\n"),OptOutMode); // Which command? Set the appropriate opt out mode switch (OptOutMode) { case 14: xprintf(PSTR("Mode 14 shenanigans\n"),n); // Or just flag that we want an opt-out packet OptOutMode=14; OptOutType=OPTOUT_START; // Assemble a mode 14 packet break; default: OptOutMode=0; returncode=1; } // Assemble the packet and break; case 'X': /* X - Exit */ return 2; case 'Y': /* Y - Version. Y2 should return a date string */ strcpy_P(str,PSTR("VBIT620 Version 0.04")); break; case '?' :; // Status TODO xprintf(PSTR("STATUS %02X\n\r"),statusI2C); // Want to know if the chips check out and the file system is OK // Video Input: xprintf(PSTR("Video input: "));report(statusI2C & 0x01); // chip responds, generating field interrupts // Digital Encoder xprintf(PSTR("Digital encoder: "));report(statusI2C & 0x02); // chip responds // FIFO statusFIFO=test2(); xprintf(PSTR("FIFO R/W verified: "));report(statusFIFO); // we can read and write to it // File system xprintf(PSTR("File system: "));report(statusDisk); // There is a card, it is formatted, it has onair/pages.all break; default: xputs(PSTR("Unknown command\n")); returncode=1; }