Ejemplo n.º 1
0
/*
 * CGI Sample: Show list of threads.
 *
 * This routine must have been registered by NutRegisterCgi() and is
 * automatically called by NutHttpProcessRequest() when the client
 * request the URL 'cgi-bin/threads.cgi'.
 */
static int ShowThreads(FILE * stream, REQUEST * req)
{
    static prog_char head[] = "<HTML><HEAD><TITLE>Threads</TITLE></HEAD><BODY><H1>Threads</H1>\r\n"
        "<TABLE BORDER><TR><TH>Handle</TH><TH>Name</TH><TH>Priority</TH><TH>Status</TH><TH>Event<BR>Queue</TH><TH>Timer</TH><TH>Stack-<BR>pointer</TH><TH>Free<BR>Stack</TH></TR>\r\n";
#if defined(__AVR__)
    static prog_char tfmt[] =
        "<TR><TD>%04X</TD><TD>%s</TD><TD>%u</TD><TD>%s</TD><TD>%04X</TD><TD>%04X</TD><TD>%04X</TD><TD>%u</TD><TD>%s</TD></TR>\r\n";
#else
    static prog_char tfmt[] =
        "<TR><TD>%08lX</TD><TD>%s</TD><TD>%u</TD><TD>%s</TD><TD>%08lX</TD><TD>%08lX</TD><TD>%08lX</TD><TD>%lu</TD><TD>%s</TD></TR>\r\n";
#endif
    static prog_char foot[] = "</TABLE></BODY></HTML>";
    static char *thread_states[] = { "TRM", "<FONT COLOR=#CC0000>RUN</FONT>", "<FONT COLOR=#339966>RDY</FONT>", "SLP" };
    NUTTHREADINFO *tdp = nutThreadList;

    /* Send HTTP response. */
    NutHttpSendHeaderTop(stream, req, 200, "Ok");
    NutHttpSendHeaderBottom(stream, req, html_mt, -1);

    /* Send HTML header. */
    fputs_P(head, stream);
    for (tdp = nutThreadList; tdp; tdp = tdp->td_next) {
        fprintf_P(stream, tfmt, (uintptr_t) tdp, tdp->td_name, tdp->td_priority,
                  thread_states[tdp->td_state], (uintptr_t) tdp->td_queue, (uintptr_t) tdp->td_timer,
                  (uintptr_t) tdp->td_sp, (uintptr_t) tdp->td_sp - (uintptr_t) tdp->td_memory,
                  *((uint32_t *) tdp->td_memory) != DEADBEEF ? "Corr" : "OK");
    }
    fputs_P(foot, stream);
    fflush(stream);

    return 0;
}
Ejemplo n.º 2
0
void system_run(void)
{	
	// Inicjacja wyprowadzeñ
	DDR(LCD_CTRLPORT) = (1<<LCD_E | 1<<LCD_RW | 1<<LCD_RS | 1<<LCD_LED); 
	PORT(LCD_CTRLPORT) = ~(1<<LCD_E | 1<<LCD_LED); 
	PORT(SW_PORT) = 1<<SW1 | 1<<SW2;
	// Inicjacja wyœwietlacza
	lcd_Init();
	lcd_SetStatus(LCD_STATUS_DISP);
	// Inicjacja timera systemowego
	TCCR2 = 1<<WGM21 /*CTC*/ | 1<<CS22 | 1<<CS21 | 1<<CS20 /*clk:1024*/;
	OCR2 = 78; // oko³o 10ms
	
	// Przerwania
	TIMSK = 1<<OCIE2 /*porównania z timera 2*/;
	sei();

	// Wyœwietlenie zapytania o jêzyk
	fputs_P(PSTR("S1 - "), lcd_GetFile());
	fputs_P(langsys_GetLangName(0), lcd_GetFile());
	lcd_GoTo(0, 1);
	fputs_P(PSTR("S2 - "), lcd_GetFile());
	fputs_P(langsys_GetLangName(1), lcd_GetFile());
	lcd_Update();
	
	// Oczekiwanie na przycisk 
	
	
	// Wywo³anie aplikacji
	app_run();
}
Ejemplo n.º 3
0
static
void one_in512_hash(uint16_t pos){
	uint8_t ctx[nessie_hash_ctx.ctx_size_B];
	uint8_t hash[(nessie_hash_ctx.hashsize_b+7)/8];
	uint8_t block[nessie_hash_ctx.blocksize_B];
	uint16_t n=512;
	char *tab[8] = { "80", "40", "20", "10",
	                 "08", "04", "02", "01" };

	pos&=511;
	fputs_P(PSTR("\n                       message="), stdout);
	fputs_P(PSTR("512-bit string: "), stdout);

	fprintf_P(stdout, PSTR("%2"PRIu16"*00,%s,%2"PRIu16"*00"), pos / 8, tab[pos & 7], 63 - pos / 8);
	
	/* now the real stuff */
	memset(block, 0, 512/8);
	block[pos>>3] = 0x80>>(pos&0x7);
	nessie_hash_ctx.hash_init(ctx);
	while(n>=nessie_hash_ctx.blocksize_B*8){
		nessie_hash_ctx.hash_next(ctx, block);
		n   -= nessie_hash_ctx.blocksize_B*8;
	}
	nessie_hash_ctx.hash_last(ctx, block, n);
	nessie_hash_ctx.hash_conv(hash, ctx);
	nessie_print_item("hash", hash, (nessie_hash_ctx.hashsize_b+7)/8);
}
Ejemplo n.º 4
0
/*
 * CGI Sample: Show list of timers.
 *
 * This routine must have been registered by NutRegisterCgi() and is
 * automatically called by NutHttpProcessRequest() when the client
 * request the URL 'cgi-bin/timers.cgi'.
 */
static int ShowTimers(FILE * stream, REQUEST * req)
{
    static prog_char head[] = "<HTML><HEAD><TITLE>Timers</TITLE></HEAD><BODY><H1>Timers</H1>\r\n";
    static prog_char thead[] =
        "<TABLE BORDER><TR><TH>Handle</TH><TH>Countdown</TH><TH>Tick Reload</TH><TH>Callback<BR>Address</TH><TH>Callback<BR>Argument</TH></TR>\r\n";
#if defined(__AVR__)
    static prog_char tfmt[] = "<TR><TD>%04X</TD><TD>%lu</TD><TD>%lu</TD><TD>%04X</TD><TD>%04X</TD></TR>\r\n";
#else
    static prog_char tfmt[] = "<TR><TD>%08lX</TD><TD>%lu</TD><TD>%lu</TD><TD>%08lX</TD><TD>%08lX</TD></TR>\r\n";
#endif
    static prog_char foot[] = "</TABLE></BODY></HTML>";
    NUTTIMERINFO *tnp;
    uint32_t ticks_left;

    NutHttpSendHeaderTop(stream, req, 200, "Ok");
    NutHttpSendHeaderBottom(stream, req, html_mt, -1);

    /* Send HTML header. */
    fputs_P(head, stream);
    if ((tnp = nutTimerList) != 0) {
        fputs_P(thead, stream);
        ticks_left = 0;
        while (tnp) {
            ticks_left += tnp->tn_ticks_left;
            fprintf_P(stream, tfmt, (uintptr_t) tnp, ticks_left, tnp->tn_ticks, (uintptr_t) tnp->tn_callback, (uintptr_t) tnp->tn_arg);
            tnp = tnp->tn_next;
        }
    }

    fputs_P(foot, stream);
    fflush(stream);

    return 0;
}
Ejemplo n.º 5
0
void shavs_setalgo(char *param){
	param = strstrip(param);
	if(param[1]=='\0'){ /* single letter specified */
		uint8_t i, option = param[0] - 'a';

		if(!shavs_algolist){
			fputs_P(PSTR("\nERROR: shavs_algolist not set!"), shavs_out_file);
			return;
		}
		for(i=0; i<=option; ++i){
			if((void*)pgm_read_word(&(shavs_algolist[i]))==NULL){
				fputs_P(PSTR("\r\nERROR: invalid selection!"), shavs_out_file);
				return;
			}
		}
		shavs_algo=(hfdesc_t*)pgm_read_word(&(shavs_algolist[option]));
	} else { /* name specifyed */
		hfdesc_t *t=NULL;
		uint8_t i=0;
		while((t=(hfdesc_t*)pgm_read_word(&(shavs_algolist[i]))) &&
		       strcasecmp_P(param, (void*)pgm_read_word(&(t->name))))
			++i;
		if(t){
			shavs_algo=t;
		}else{
		    fprintf_P(shavs_out_file, PSTR("\nERROR: could not find \"%s\"!"), param);
			cli_putstr_P(PSTR("\r\nERROR: could not find \""));
			cli_putstr(param);
			cli_putstr_P(PSTR("\"!"));
		}
	}
}
Ejemplo n.º 6
0
void wifi_connect() {
  char response[256];
  char response_len;

  printf_P(PSTR("[WIFI] Connecting...\n"));

  wifi_enable();
  _delay_ms(50);

  // Reset wireless
  fputs_P(AT_RST, serial_output);
  _delay_ms(50);
  while(serial_available()) fgetc(serial_input);

  wifi_repeat_until_ok("AT\r\n");

  fputs_P(AT_CWMODE_1, serial_output);
  _delay_ms(50);
  print_response();

  fprintf_P(serial_output, AT_CWJAP, WIFI_SSID, WIFI_PASS);
  print_response();

  // TODO: Retry connect after x failures
  while(!wifi_is_connected());

  fputs_P(AT_CIPMUX_0, serial_output);
  print_response();

  printf_P(PSTR("[WIFI] Connected.\n"));
}
void net_sendHeadToDB(uint16_t len){
  // this sends the HTTP/Json header for a transmission.
  // 1st line: POST /{name_db}/_design/{doc_db}/_update/{func_db} HTTP/1.1
  fputs_P(PSTR("POST /"), &sock_stream);
  fputs(cfg.name_db, &sock_stream);
  fputs_P(PSTR("/_design/"), &sock_stream);
  fputs(cfg.doc_db, &sock_stream);
  fputs_P(PSTR("/_update/"), &sock_stream);
  fputs(cfg.func_db, &sock_stream);
  fputs_P(PSTR(" HTTP/1.1\n"), &sock_stream);
  // 2nd line: Host: {ip}:{port}
  fputs_P(PSTR("Host: "), &sock_stream);
  fprintf_P(&sock_stream, UintDot_4Colon, cfg.ip_db[0], cfg.ip_db[1], cfg.ip_db[2], cfg.ip_db[3], cfg.port_db);
  fputc('\n', &sock_stream);
  // 3rd line: Cookie: AuthSession="{cookie_db}"
  fputs_P(PSTR("Cookie: AuthSession="), &sock_stream);
  fputs(cfg.cookie_db, &sock_stream);
  fputc('\n', &sock_stream);
  // 4th line: X-CouchDB-WWW-Authenticate: Cookie
  fputs_P(PSTR("X-CouchDB-WWW-Authenticate: Cookie\n"), &sock_stream);
  // 5rd line: Content-type: application/json
  fputs_P(PSTR("Content-type: application/json\n"), &sock_stream);
  // 6th line: Content-Length: {len}
  fprintf_P(&sock_stream, PSTR("Content-Length: %u\n"), len);
  if(len>0){
    // 7th line: \newline
    fputc('\n', &sock_stream);
    // 8th line: {data}
  }
}
void net_loop(){
  // main networking loop
  // this handles the user interface, but also repiles from couchdb

	switch(ui_state){
		case UI_READY:
			serve();
      handle_db_response();
			break;
		case UI_TWILOCK:
			// we do not process new socket inputs, as we have to wait for the twi bus to become ready:
			if(twi_try_lock_bus()){
				// we aquired the bus
				// now we have to do our access as fast as possible, as others might wait for bus access:
				// call command handler, who waits for access to the bus:
				twi_access_fun();
				
				fputs_P(PSTR("% "), &sock_stream);
				sock_stream_flush();
				// we again accept commands
				ui_state = UI_READY;
				twi_free_bus();
				int16_t b;
				while((b=fgetc(&sock_stream)) != EOF){
					if(b == '\n' || b == ';'){
						break;
					}
				}
				// handle other already existing commands in the buffer
				//ui_handleCMD(stream_get_sock());
			}
			break;
	}
}
Ejemplo n.º 9
0
static
void tv4_hash(void){
	uint8_t ctx[nessie_hash_ctx.ctx_size_B];
	uint8_t hash[(nessie_hash_ctx.hashsize_b+7)/8];
	uint8_t block[nessie_hash_ctx.hashsize_b/8];
	uint16_t n=nessie_hash_ctx.hashsize_b;
	uint32_t i;
	
	fputs_P(PSTR("\r\n                       message="), stdout);
	fprintf_P(stdout, PSTR("%"PRIu16" zero bits"), nessie_hash_ctx.hashsize_b);

	memset(block, 0, nessie_hash_ctx.hashsize_b/8);
	
	nessie_hash_ctx.hash_init(ctx);
	while(n>=nessie_hash_ctx.blocksize_B*8){
		nessie_hash_ctx.hash_next(ctx, block);
		n    -= nessie_hash_ctx.blocksize_B*8;
	}
	nessie_hash_ctx.hash_last(ctx, block, n);
	nessie_hash_ctx.hash_conv(hash, ctx);
	nessie_print_item("hash", hash, (nessie_hash_ctx.hashsize_b+7)/8);
	if(nessie_hash_quick)
		return;
	for(i=1; i<100000L; ++i){ /* this assumes BLOCKSIZE >= HASHSIZE */
		nessie_hash_ctx.hash_init(ctx);
		nessie_hash_ctx.hash_last(ctx, hash, nessie_hash_ctx.hashsize_b);
		nessie_hash_ctx.hash_conv(hash, ctx);
		NESSIE_SEND_ALIVE_A(i);
	}
	nessie_print_item("iterated 100000 times", hash, (nessie_hash_ctx.hashsize_b+7)/8);
}
Ejemplo n.º 10
0
int main(void)
{
	uint8_t u8a, u8b;
	uint16_t u16a, u16b, u16c;
	uint32_t u32a;
	///////////////////////////////////////////////
	// Inicjacja portu szeregowego
	RS_SET_BAUD(DEF_BAUD); 
	UCSR0C = 1<<URSEL0 | 1<<UCSZ01 | 1<<UCSZ00; 
	UCSR0B = 1<<RXEN0 | 1<<TXEN0; 
	UCSR0A = 0;
	// Koniec inicjacji
	///////////////////////////////////////////////
	// Inicjacja funkcji dla domyœlnych strumieni we/wy
	//fRS = fdevopen(rs_put, rs_get, 0);
	
	fputs_P(PSTR("Hello world!\r\n"), fRS);
	
	u8a = 100;
	u8b = 200;
	u8a = (u8b * u8a) / 100;
	fprintf_P(fRS, PSTR("8x8 Wynik %u\r\n"),(unsigned int)u8a);
	
	u16a = 200;
	u16b = 600;
	u16a = (u16b * u16a) / 100;
	fprintf_P(fRS, PSTR("16x16 Wynik %u\r\n"),(unsigned int)u16c);
	
	u16c = (uint32_t)(u16a * u16b) / 10;
	fprintf_P(fRS, PSTR("(32)(16x16) Wynik: %u\r\n"), (unsigned int)u16c);
	
	u16c = ((uint32_t)u16a * (uint32_t)u16b) / 10;
	fprintf_P(fRS, PSTR("(32)16x(32)16 Wynik: %u\r\n"), (unsigned int)u16c);
	
	u16c = ((uint32_t)u16a * u16b) / 10;
	fprintf_P(fRS, PSTR("(32)16x16 Wynik: %u\r\n"), (unsigned int)u16c);
	
	u32a = u16a * u16b;
	fprintf_P(fRS, PSTR("32=16x16 Wynik: %lu\r\n"), (unsigned long int)u32a);
	
	u32a = (uint32_t)u16a * u16b;
	fprintf_P(fRS, PSTR("32=(32)16x16 Wynik: %lu\r\n"), (unsigned long int)u32a);

	fputs_P(PSTR("Koniec\r\n"), fRS);
}
Ejemplo n.º 11
0
void shavs_listalgos(void){
	char option = 'a';

	hfdesc_t *t;
	uint8_t i=0;
	fputs_P(PSTR("\nthe following algorithms are available:\n"), shavs_out_file);
	while(option <= 'z' && (t = (hfdesc_t*)pgm_read_word(&(shavs_algolist[i])))){
	    fprintf_P(shavs_out_file, PSTR("\t%c%c:\t%S\n"),
	        (t == shavs_algo) ? '*' : ' ', option++, pgm_read_word(&(t->name)));
		i++;
	}
}
Ejemplo n.º 12
0
static
void amillion_hash(void){
	uint8_t ctx[nessie_hash_ctx.ctx_size_B];
	uint8_t hash[(nessie_hash_ctx.hashsize_b+7)/8];
	uint8_t block[nessie_hash_ctx.blocksize_B];
	uint32_t n=1000000LL;
	uint16_t i=0;
	
	fputs_P(PSTR("\n                       message="), stdout);
	fputs_P(PSTR("1 million times \"a\""), stdout);
	memset(block, 'a', nessie_hash_ctx.blocksize_B);
	nessie_hash_ctx.hash_init(ctx);
	while(n>=nessie_hash_ctx.blocksize_B){
		nessie_hash_ctx.hash_next(ctx, block);
		n    -= nessie_hash_ctx.blocksize_B;
		NESSIE_SEND_ALIVE_A(i++);
	}
	nessie_hash_ctx.hash_last(ctx, block, n*8);
	nessie_hash_ctx.hash_conv(hash, ctx);
	nessie_print_item("hash", hash, (nessie_hash_ctx.hashsize_b+7)/8);
}
Ejemplo n.º 13
0
/*  Return pointer to a new uninitialized task struct. Return NULL if out of memory.
 */
static task_t *allocTask(void)
{
    uint8_t i;
    
    for (i=0; i < sizeof tasks / sizeof tasks[0]; i++) {
        if (tasks[i].type == TASK_EMPTY) {
            return &tasks[i];
        }
    }
    fputs_P(PSTR("allocTask: Out of memory.\r\n"), debug);
    return NULL;
}
Ejemplo n.º 14
0
static
void ascii_hash_P(PGM_P data, PGM_P desc){
	uint8_t ctx[nessie_hash_ctx.ctx_size_B];
	uint8_t hash[HASHSIZE_B];
	uint16_t sl;
	uint8_t buffer[BLOCKSIZE_B];
	
	fputs_P(PSTR("\n                       message="), stdout);
	fputs_P(desc, stdout);
	nessie_hash_ctx.hash_init(ctx);
	sl = strlen_P(data);
	while(sl>=BLOCKSIZE_B){
		memcpy_P(buffer, data, BLOCKSIZE_B);
		nessie_hash_ctx.hash_next(ctx, buffer);
		data += BLOCKSIZE_B;
		sl   -= BLOCKSIZE_B;
	}
	memcpy_P(buffer, data, sl);
	nessie_hash_ctx.hash_last(ctx, buffer, sl*8);
	nessie_hash_ctx.hash_conv(hash, ctx);
	nessie_print_item("hash", hash, (nessie_hash_ctx.hashsize_b+7)/8);
}
Ejemplo n.º 15
0
/*
 * CGI Sample: Proccessing a form.
 *
 * This routine must have been registered by NutRegisterCgi() and is
 * automatically called by NutHttpProcessRequest() when the client
 * request the URL 'cgi-bin/form.cgi'.
 *
 * Thanks to Tom Boettger, who provided this sample for ICCAVR.
 */
int ShowForm(FILE * stream, REQUEST * req)
{
    static prog_char html_head[] = "<HTML><BODY><BR><H1>Form Result</H1><BR><BR>";
    static prog_char html_body[] = "<BR><BR><p><a href=\"../index.html\">return to main</a></BODY></HTML></p>";

    NutHttpSendHeaderTop(stream, req, 200, "Ok");
    NutHttpSendHeaderBottom(stream, req, html_mt, -1);

    /* Send HTML header. */
    fputs_P(html_head, stream);

    if (req->req_query) {
        char *name;
        char *value;
        int i;
        int count;

        count = NutHttpGetParameterCount(req);
        /* Extract count parameters. */
        for (i = 0; i < count; i++) {
            name = NutHttpGetParameterName(req, i);
            value = NutHttpGetParameterValue(req, i);

            /* Send the parameters back to the client. */

#ifdef __IMAGECRAFT__
            fprintf(stream, "%s: %s<BR>\r\n", name, value);
#else
            fprintf_P(stream, PSTR("%s: %s<BR>\r\n"), name, value);
#endif
        }
    }

    fputs_P(html_body, stream);
    fflush(stream);

    return 0;
}
Ejemplo n.º 16
0
static int CgiAnalogueInputsRow( FILE * stream, int row_no )
{

    if(row_no < 0)
    {
        static prog_char th[] = "<TR><TH> Driver </TH><TH> Property </TH><TH> Value </TH></TR>\r\n";
        fputs_P(th, stream);
        return 1;
    }

    // scan through drivers

    if( row_no >= n_major_total )
        return 0;

    dev_major *dev = devices[row_no];

    static prog_char tfmt[] = "<TR><TD> %s </TD><TD> %s </TD><TD> </TD></TR>\r\n";
    fprintf_P(stream, tfmt, dev->name, dev->started ? "run" : "stop" );

    if( dev->prop )
    {
        if(DEBUG) printf("%s has properties\n", dev->name );
        int nprop = 0;
        for(;;)
        {
            char pName[32];
            char buf2[32] = "(?)";

            errno_t rc = dev_drv_listproperties( dev, nprop++, pName, sizeof(pName)-1 );
            if( rc )
                break;

            uint8_t rw = dev_drv_property_rw( dev, pName );

            rc = dev_drv_getproperty( dev, pName, buf2, sizeof(buf2)-1 );
            if( rc && DEBUG )
                printf("dev_drv_getproperty() = %d\n", rc);

            static prog_char tfmt2[] = "<TR><TD> </TD><TD> %s </TD><TD>= %s %s</TD></TR>\r\n";
            fprintf_P(stream, tfmt2, pName, buf2, rw ? "(rw)" : "(ro)" );
        }

    }

    return 1;
}
Ejemplo n.º 17
0
static int CgiOutputsRow( FILE * stream, int row_no )
{

    if(row_no < 0)
    {
        //static prog_char th[] = "<TR><TH> Channel </TH><TH> &nbsp;&nbsp; </TH><TH> Value </TH></TR>\r\n";
        static prog_char th[] = "<TR><TH width=\"150\"> Dev </TH><TH width=\"150\"> Channel </TH><TH width=\"150\"> Value </TH><TH width=\"150\"> IO </TH><TH width=\"150\"> Err </TH></TR>\r\n";
        fputs_P(th, stream);
        return 1;
    }

    if( row_no  <  n_minor_total )
    {
        dev_minor *minor = dev_get_minor( row_no );

        char buf[32] = "";

        if( minor->number == 0 )
        {
            dev_major* d = minor->dev;

            if( d->to_string )
                d->to_string( minor, buf, sizeof(buf) );

            static prog_char dh[] = "<TR><td> %s </td><td>  </td><td> %s </td><td>  </td><td>  </td></TR>\r\n";
            fprintf_P(stream, dh, d->name, buf );
        }

        //buf[0] = '?';
        //buf[1] = 0;
        if(minor->to_string)
        {
            static prog_char mh[] = "<TR><td>  </td><td> %s </td><td> %s </td><td> %u </td><td> %u </td></TR>\r\n";
            //int8_t ret =
            uint8_t rc = minor->to_string( minor, buf, sizeof(buf) );
            if(!rc) fprintf_P(stream, mh, minor->name, buf, minor->io_count, minor->err_count );
        }

        return 1;
    }

    row_no -= n_minor_total;


    return 0;
}
Ejemplo n.º 18
0
static
void zero_hash(uint16_t n){
	uint8_t ctx[nessie_hash_ctx.ctx_size_B];
	uint8_t hash[(nessie_hash_ctx.hashsize_b+7)/8];
	uint8_t block[nessie_hash_ctx.blocksize_B];
	
	fputs_P(PSTR("\n                       message="), stdout);
	fprintf_P(stdout, PSTR("%"PRIu16" zero bits"));
	
	memset(block, 0, nessie_hash_ctx.blocksize_B); 
	nessie_hash_ctx.hash_init(ctx);
	while(n>=nessie_hash_ctx.blocksize_B*8){
		nessie_hash_ctx.hash_next(ctx, block);
		n   -= nessie_hash_ctx.blocksize_B*8;
	}
	nessie_hash_ctx.hash_last(ctx, block, n);
	nessie_hash_ctx.hash_conv(hash, ctx);
	nessie_print_item("hash", hash, (nessie_hash_ctx.hashsize_b+7)/8);
}
Ejemplo n.º 19
0
bool wifi_is_connected() {
  char line[32];
  bool connected = false;

  while(serial_available()) fgetc(serial_input);

  fputs_P(AT_CWJAPq, serial_output);

  _delay_ms(50);

  while(!connected && serial_available()) {
    fgets(line, ARRAYSIZE(line), serial_input);
    connected = MEMCMP_CONST(line, "OK\r\n") == 0;
  }

  while(serial_available()) fgetc(serial_input);

  return connected;
}
Ejemplo n.º 20
0
static int CgiNetworkRow( FILE * stream, int row_no )
{

    if(row_no < 0)
    {
        static prog_char th[] = "<TR><TH> Type </TH><TH> Name </TH><TH> Value </TH></TR>\r\n";
        fputs_P(th, stream);
        return 1;
    }

    switch( row_no )
    {
    case 0:
    {
        static prog_char tfmt[] = "<TR><TD>&nbsp;MAC Address&nbsp;</TD><TD>&nbsp;MAC&nbsp;</TD><TD>&nbsp;%02X:%02X:%02X:%02X:%02X:%02X&nbsp;</TD></TR>\r\n";
        fprintf_P(stream, tfmt,
                  ee_cfg.mac_addr[0], ee_cfg.mac_addr[1], ee_cfg.mac_addr[2],
                  ee_cfg.mac_addr[3], ee_cfg.mac_addr[4], ee_cfg.mac_addr[5]
                 );

    }
    break;

    case 1: put_addr_row( stream, 0, "Net Mask", confnet.cdn_ip_mask );		break;
    case 2: put_addr_row( stream, 0, "Current", confnet.cdn_ip_addr );       	break;
    case 3: put_addr_row( stream, 0, "Configured", confnet.cdn_cip_addr );	break;
    case 4: put_addr_row( stream, 0, "Gateway", confnet.cdn_gateway );		break;

    case 5: put_addr_row( stream, 0, "EEPROM Net Mask", ee_cfg.ip_mask );	break;
    case 6: put_addr_row( stream, 0, "EEPROM Address", ee_cfg.ip_addr );       	break;

    case 7: put_addr_row( stream, 0, "EEPROM NNTP server", ee_cfg.ip_nntp );	break;
    case 8: put_addr_row( stream, 0, "EEPROM Syslog server", ee_cfg.ip_syslog );break;

    default:
        return 0;
    }

    return 1;
}
void net_sendResultToDB(struct dummy_packet *packets, uint8_t board_addr){
  // Sends a set of 8 measurement results to the couchdb database

  int8_t sensor_index;
  int8_t comma_flag = 0;
  int16_t value;
  uint16_t len=0;
  PORTB &= ~(1<<PB1);
  PORTD &= ~(1<<PD5);
  if( W5100.readSnSR(DB_CLIENT_SOCK) != SnSR::ESTABLISHED ){
    if(!connect_db(cfg.port+1)){
      return;
    }
  }
  // Calculate length for the JSON header:
  for (sensor_index=0; sensor_index<8; sensor_index++){
    if(packets[sensor_index].header.error && packets[sensor_index].header.connected){
      // We do not send data, which might have an error
      continue;
    }
    if(packets[sensor_index].header.connected){
      switch(packets[sensor_index].header.type){
        case PACKET_TYPE_TSIC:
          len += JSON_TEMP_LEN;
          // length of "," or "}" at the end
          len++;
          break;
        case PACKET_TYPE_HYT:
          // There is no difference in temperature length
          // for HYT and TSIC.
          len += JSON_TEMP_LEN;
          len++;
          len += JSON_HUM_LEN;
          len++;
          break;
        default:
          break;
      }
    }
  }
  PORTB |= (1<<PB1);
  if(len==0){
    return;
  }
  len+=JSON_PREFIX_LEN;
  // length of "}" at the end
  len++;

  // Now we start sending data to couchdb
  stream_set_sock(DB_CLIENT_SOCK);
  net_sendHeadToDB(len);
#ifdef DEBUG
  printf_P(PSTR("Send Head \n\r"));
#endif

  /* convert packet data to json format
   * {"type":"value","data",{"bdddsdTEMP":"ddd.dd","bdddsdHUM":"ddd.dd"}}
   */
  fputs_P(PSTR(JSON_PREFIX), &sock_stream);
#ifdef DEBUG
  printf_P(PSTR("Send PREFIX \n\r"));
#endif
  comma_flag = 0;
  //puts_P(PSTR("+"));
  PORTB &= ~(1<<PB1);
  PORTD |= (1<<PD5);
  for (sensor_index=0;sensor_index<8;sensor_index++){
    if(packets[sensor_index].header.error && packets[sensor_index].header.connected){
      continue;
    }
    if(packets[sensor_index].header.connected){
      switch(packets[sensor_index].header.type){
        case PACKET_TYPE_TSIC:
          if(comma_flag){
            fputc(',', &sock_stream);
          }else{
            comma_flag = 1; 
          }
          value =  ((struct tsic_packet *)(packets))[sensor_index].temperature;
          fprintf_P(&sock_stream, PSTR(JSON_TEMP), JSON_OUTPUT);
#ifdef DEBUG
          printf_P(PSTR("Send temperature \n\r"));
#endif
          break;
        case PACKET_TYPE_HYT:
          if(comma_flag){
            fputc(',', &sock_stream);
          }else{
            comma_flag = 1; 
          }
          value = ((struct hyt_packet *)(packets))[sensor_index].temperature;
          fprintf_P(&sock_stream, PSTR(JSON_TEMP), JSON_OUTPUT);
          value = ((struct hyt_packet *)(packets) )[sensor_index].humidity;
          fputc(',', &sock_stream);
          fprintf_P(&sock_stream, PSTR(JSON_HUM), JSON_OUTPUT); 
          break;
        default:
          break;
      }
    }
  }
  fputc('}', &sock_stream);
  fputc('}', &sock_stream);
#ifdef DEBUG
  printf_P(PSTR("Send finished \n\r"));
#endif
  sock_stream_flush();
  PORTB |= (1<<PB1);
}
Ejemplo n.º 22
0
void shavs_test1(void){ /* KAT tests */
	uint32_t length=0;
	int32_t expect_input=0;

	if(!shavs_algo){
			fputs_P(PSTR("\r\nERROR: select algorithm first!"), shavs_out_file);
		return;
	}
	char c;
	uint8_t diggest[pgm_read_word(&(shavs_algo->hashsize_b))/8];
	shavs_ctx.buffersize_B=pgm_read_word(&(shavs_algo->blocksize_b))/8;
	uint8_t buffer[shavs_ctx.buffersize_B+5];
	shavs_ctx.buffer = buffer;
	fprintf_P(shavs_out_file, PSTR("\nbuffer_size = 0x%04"PRIx16" bytes"), shavs_ctx.buffersize_B);
	for(;;){
		shavs_ctx.blocks = 0;
		memset(buffer, 0, shavs_ctx.buffersize_B);
		length = getLength();
		if(length<0){
			return;
		}

#if DEBUG
		fprintf_P(shavs_out_file, PSTR("\nLen == %"PRIu32), length)
#endif
		if(length==0){
			expect_input=2;
		}else{
			expect_input=((length + 7) >> 2) & (~1L);
		}
#if DEBUG
		fprintf_P(shavs_out_file, PSTR("\r\nexpected_input == %"PRId32), expected_input);
#endif
		shavs_ctx.buffer_idx = 0;
		shavs_ctx.in_byte    = 0;
		shavs_ctx.blocks     = 0;
		uint8_t ret;
#if DEBUG
		fprintf_P(shavs_out_file, PSTR("\n HFAL init\n (2) expected_input == "), expected_input);
#endif
		ret = hfal_hash_init(shavs_algo, &(shavs_ctx.ctx));
		if(ret){
			fprintf_P(shavs_out_file, PSTR("\r\n HFAL init returned with: %"PRIx8), ret);
			return;
		}
#if DEBUG
		fprintf_P(shavs_out_file, PSTR("\r\n (3) expected_input == %"PRId32"\n"), expected_input)
#endif
		while((c=cli_getc_cecho())!='M' && c!='m'){
			if(!isblank(c)){
			    fprintf_P(shavs_out_file, PSTR("\nERROR: wrong input (1) [0x%"PRIx8"]!\n"), c);
				hfal_hash_free(&(shavs_ctx.ctx));
				return;
			}
		}
		if((c=cli_getc_cecho())!='s' && c!='S'){
            fputs_P(PSTR("\nERROR: wrong input (2)!\n"), shavs_out_file);
            hfal_hash_free(&(shavs_ctx.ctx));
            return;
		}
		if((c=cli_getc_cecho())!='g' && c!='G'){
            fputs_P(PSTR("\nERROR: wrong input (3)!\n"), shavs_out_file);
            hfal_hash_free(&(shavs_ctx.ctx));
            return;
		}
		while((c=cli_getc_cecho())!='='){
			if(!isblank(c)){
                fputs_P(PSTR("\nERROR: wrong input (4)!\n"), shavs_out_file);
				hfal_hash_free(&(shavs_ctx.ctx));
				return;
			}
		}
#if DEBUG
		fputs_P(PSTR("\r\nparsing started"), shavs_out_file);
#endif
		shavs_ctx.buffer_idx = 0;
		shavs_ctx.in_byte    = 0;
		shavs_ctx.blocks     = 0;
		while(expect_input>0){
			c=cli_getc_cecho();
#if DEBUG
			fprintf_P(shavs_out_file, PSTR("\n\t(%"PRId32") "), expected_input);
			_delay_ms(500);
#endif
			if(buffer_add(c)==0){
				--expect_input;
			}else{
				if(!isblank((uint16_t)c)){
				    fprintf_P(shavs_out_file, PSTR("\nERROR: wrong input (5) (%c)!\n"), c);
					hfal_hash_free(&(shavs_ctx.ctx));
					return;
				}
			}
		}
#if DEBUG
		cli_putstr_P(PSTR("\r\nBuffer-A:"));
		cli_hexdump_block(buffer, shavs_ctx.buffersize_B, 5, 8);

		cli_putstr_P(PSTR("\r\n starting finalisation"));
		cli_putstr_P(PSTR("\r\n\tblocks     == "));
		cli_hexdump_rev(&(shavs_ctx.blocks),4);
		cli_putstr_P(PSTR("\r\n\tbuffer_idx == "));
		cli_hexdump_rev(&(shavs_ctx.buffer_idx),2);
		cli_putstr_P(PSTR("\r\n\tin_byte    == "));
		cli_hexdump_rev(&(shavs_ctx.in_byte),1);
		_delay_ms(500);

		cli_putstr_P(PSTR("\r\n starting last block"));
		cli_putstr_P(PSTR("\r\n\tlength       == "));
		cli_hexdump_rev(&length,4);
		cli_putstr_P(PSTR("\r\n\tbuffersize_B == "));
		cli_hexdump_rev(&(shavs_ctx.buffersize_B),2);
		uint16_t temp=length-(shavs_ctx.blocks)*((shavs_ctx.buffersize_B)*8);
		cli_putstr_P(PSTR("\r\n\t (temp)      == "));
		cli_hexdump_rev(&temp,2);
		_delay_ms(500);
		temp=length-(shavs_ctx.blocks)*((shavs_ctx.buffersize_B)*8);
#else
		uint16_t temp=length-(shavs_ctx.blocks)*((shavs_ctx.buffersize_B)*8);
#endif
		hfal_hash_lastBlock( &(shavs_ctx.ctx), buffer, /* be aware of freaking compilers!!! */
		                    temp );
#if DEBUG
		cli_putstr_P(PSTR("\r\n starting ctx2hash"));
		_delay_ms(500);
#endif
		hfal_hash_ctx2hash(diggest, &(shavs_ctx.ctx));
#if DEBUG
		cli_putstr_P(PSTR("\r\n starting hash free"));
#endif
		hfal_hash_free(&(shavs_ctx.ctx));
		cli_putstr_P(PSTR("\r\n MD = "));
		cli_hexdump(diggest, pgm_read_word(&(shavs_algo->hashsize_b))/8);

	}
}
Ejemplo n.º 23
0
/*!
 * \brief Wait for a specific string to appear.
 *
 * \param ci  Pointer to a NUTCHAT structure, which must have been 
 *            created by NutChatCreate().
 * \param str Expected string. May be empty if nothing is expected.
 *
 * \return 0 on success, 3 in case of a timeout error while waiting
 *         for an expected string, or the index of an abort string 
 *         plus 4, if one has been received. 
 */
int NutChatExpectString(NUTCHAT * ci, char *str)
{
    char ch;
    uint8_t m;
    uint8_t i;
    char *cp = str;

#ifdef NUTDEBUG
    if (__chat_trf) {
        static prog_char dbgfmt[] = "Expect '%s', got '";
        fprintf_P(__chat_trs, dbgfmt, str);
    }
#endif

    while (*cp) {

        /*
         * Read the next character. Return on timeout.
         */
        if (_read(ci->chat_fd, &ch, 1) != 1) {
#ifdef NUTDEBUG
            if (__chat_trf) {
                static prog_char dbgmsg[] = "' TIMEOUT\n";
                fputs_P(dbgmsg, __chat_trs);
            }
#endif
            return 3;
        }
#ifdef NUTDEBUG
        if (__chat_trf) {
            if (ch > 31 && ch < 127) {
                fputc(ch, __chat_trs);
            } else {
                fprintf(__chat_trs, "\\x%02X", ch);
            }
        }
#endif
        /*
         * If the character doesn't match the next expected one,
         * then restart from the beginning of the expected string.
         */
        if (ch != *cp) {
            cp = str;
        }

        /*
         * If the character matched, advance the pointer into
         * the expected string.
         */
        if (ch == *cp) {
            cp++;
        }

        /*
         * Check for abort strings.
         */
        for (i = 0; i < ci->chat_aborts; i++) {
            m = ci->chat_abomat[i];
            if (ch == ci->chat_abort[i][m]) {
                if (ci->chat_abort[i][++m] == 0) {
#ifdef NUTDEBUG
                    if (__chat_trf) {
                        static prog_char dbgmsg[] = "' ABORT\n";
                        fputs_P(dbgmsg, __chat_trs);
                    }
#endif
                    return i + 4;
                }
            } else
                m = (ch == ci->chat_abort[i][0]);
            ci->chat_abomat[i] = m;
        }

        /*
         * Check for report strings.
         */
        if (ci->chat_report_state > 0) {
            m = ci->chat_repmat;
            if (ci->chat_report_state == 2) {
                chat_report[m++] = ch;
            } else if (ch == ci->chat_report_search[m]) {
                chat_report[m++] = ch;
                if (ci->chat_report_search[m] == 0) {
                    ci->chat_report_state = 2;
                }
            } else {
                m = (ch == ci->chat_report_search[0]);
            }
            ci->chat_repmat = m;
        }
    }

    /*
     * Read the remainder of the string before NutChatSendString clears it
     */
    if (ci->chat_report_state == 2) {
        m = ci->chat_repmat;    /* not needed... (but not nice to remove it) */
        while (m < CHAT_MAX_REPORT_SIZE) {
            if (_read(ci->chat_fd, &ch, 1) != 1 || ch < ' ') {
                break;
            }
            chat_report[m++] = ch;

#ifdef NUTDEBUG
            if (__chat_trf) {
                if (ch > 31 && ch < 127) {
                    fputc(ch, __chat_trs);
                } else {
                    fprintf(__chat_trs, "\\x%02X", ch);
                }
            }
#endif
        }
        ci->chat_report_state = 0;      /* Only find first occurence */
        chat_report[m] = 0;
    }
#ifdef NUTDEBUG
    if (__chat_trf) {
        static prog_char dbgmsg[] = "'\n";
        fputs_P(dbgmsg, __chat_trs);
    }
#endif

    return 0;
}
Ejemplo n.º 24
0
/*
 * CGI Sample: Show list of sockets.
 *
 * This routine must have been registered by NutRegisterCgi() and is
 * automatically called by NutHttpProcessRequest() when the client
 * request the URL 'cgi-bin/sockets.cgi'.
 */
static int ShowSockets(FILE * stream, REQUEST * req)
{
    /* String literals are kept in flash ROM. */
    static prog_char head[] = "<HTML><HEAD><TITLE>Sockets</TITLE></HEAD>"
        "<BODY><H1>Sockets</H1>\r\n"
        "<TABLE BORDER><TR><TH>Handle</TH><TH>Type</TH><TH>Local</TH><TH>Remote</TH><TH>Status</TH></TR>\r\n";
#if defined(__AVR__)
    static prog_char tfmt1[] = "<TR><TD>%04X</TD><TD>TCP</TD><TD>%s:%u</TD>";
#else
    static prog_char tfmt1[] = "<TR><TD>%08lX</TD><TD>TCP</TD><TD>%s:%u</TD>";
#endif
    static prog_char tfmt2[] = "<TD>%s:%u</TD><TD>";
    static prog_char foot[] = "</TABLE></BODY></HTML>";
    static prog_char st_listen[] = "LISTEN";
    static prog_char st_synsent[] = "SYNSENT";
    static prog_char st_synrcvd[] = "SYNRCVD";
    static prog_char st_estab[] = "<FONT COLOR=#CC0000>ESTABL</FONT>";
    static prog_char st_finwait1[] = "FINWAIT1";
    static prog_char st_finwait2[] = "FINWAIT2";
    static prog_char st_closewait[] = "CLOSEWAIT";
    static prog_char st_closing[] = "CLOSING";
    static prog_char st_lastack[] = "LASTACK";
    static prog_char st_timewait[] = "TIMEWAIT";
    static prog_char st_closed[] = "CLOSED";
    static prog_char st_unknown[] = "UNKNOWN";
    prog_char *st_P;
    extern TCPSOCKET *tcpSocketList;
    TCPSOCKET *ts;

    NutHttpSendHeaderTop(stream, req, 200, "Ok");
    NutHttpSendHeaderBottom(stream, req, html_mt, -1);

    /* Send HTML header. */
    fputs_P(head, stream);
    for (ts = tcpSocketList; ts; ts = ts->so_next) {
        switch (ts->so_state) {
        case TCPS_LISTEN:
            st_P = (prog_char *) st_listen;
            break;
        case TCPS_SYN_SENT:
            st_P = (prog_char *) st_synsent;
            break;
        case TCPS_SYN_RECEIVED:
            st_P = (prog_char *) st_synrcvd;
            break;
        case TCPS_ESTABLISHED:
            st_P = (prog_char *) st_estab;
            break;
        case TCPS_FIN_WAIT_1:
            st_P = (prog_char *) st_finwait1;
            break;
        case TCPS_FIN_WAIT_2:
            st_P = (prog_char *) st_finwait2;
            break;
        case TCPS_CLOSE_WAIT:
            st_P = (prog_char *) st_closewait;
            break;
        case TCPS_CLOSING:
            st_P = (prog_char *) st_closing;
            break;
        case TCPS_LAST_ACK:
            st_P = (prog_char *) st_lastack;
            break;
        case TCPS_TIME_WAIT:
            st_P = (prog_char *) st_timewait;
            break;
        case TCPS_CLOSED:
            st_P = (prog_char *) st_closed;
            break;
        default:
            st_P = (prog_char *) st_unknown;
            break;
        }
        /*
         * Fixed a bug reported by Zhao Weigang.
         */
        fprintf_P(stream, tfmt1, (uintptr_t) ts, inet_ntoa(ts->so_local_addr), ntohs(ts->so_local_port));
        fprintf_P(stream, tfmt2, inet_ntoa(ts->so_remote_addr), ntohs(ts->so_remote_port));
        fputs_P(st_P, stream);
        fputs("</TD></TR>\r\n", stream);
        fflush(stream);
    }

    fputs_P(foot, stream);
    fflush(stream);

    return 0;
}
Ejemplo n.º 25
0
/*
 * CGI Sample: Show request parameters.
 *
 * See httpd.h for REQUEST structure.
 *
 * This routine must have been registered by NutRegisterCgi() and is
 * automatically called by NutHttpProcessRequest() when the client
 * request the URL 'cgi-bin/test.cgi'.
 */
static int ShowQuery(FILE * stream, REQUEST * req)
{
    char *cp;
    /*
     * This may look a little bit weird if you are not used to C programming
     * for flash microcontrollers. The special type 'prog_char' forces the
     * string literals to be placed in flash ROM. This saves us a lot of
     * precious RAM.
     */
    static prog_char head[] = "<HTML><HEAD><TITLE>Parameters</TITLE></HEAD><BODY><H1>Parameters</H1>";
    static prog_char foot[] = "</BODY></HTML>";
    static prog_char req_fmt[] = "Method: %s<BR>\r\nVersion: HTTP/%d.%d<BR>\r\nContent length: %ld<BR>\r\n";
    static prog_char url_fmt[] = "URL: %s<BR>\r\n";
    static prog_char query_fmt[] = "Argument: %s<BR>\r\n";
    static prog_char type_fmt[] = "Content type: %s<BR>\r\n";
    static prog_char cookie_fmt[] = "Cookie: %s<BR>\r\n";
    static prog_char auth_fmt[] = "Auth info: %s<BR>\r\n";
    static prog_char agent_fmt[] = "User agent: %s<BR>\r\n";

    /* These useful API calls create a HTTP response for us. */
    NutHttpSendHeaderTop(stream, req, 200, "Ok");
    NutHttpSendHeaderBottom(stream, req, html_mt, -1);

    /* Send HTML header. */
    fputs_P(head, stream);

    /*
     * Send request parameters.
     */
    switch (req->req_method) {
    case METHOD_GET:
        cp = "GET";
        break;
    case METHOD_POST:
        cp = "POST";
        break;
    case METHOD_HEAD:
        cp = "HEAD";
        break;
    default:
        cp = "UNKNOWN";
        break;
    }
    fprintf_P(stream, req_fmt, cp, req->req_version / 10, req->req_version % 10, req->req_length);
    if (req->req_url)
        fprintf_P(stream, url_fmt, req->req_url);
    if (req->req_query)
        fprintf_P(stream, query_fmt, req->req_query);
    if (req->req_type)
        fprintf_P(stream, type_fmt, req->req_type);
    if (req->req_cookie)
        fprintf_P(stream, cookie_fmt, req->req_cookie);
    if (req->req_auth)
        fprintf_P(stream, auth_fmt, req->req_auth);
    if (req->req_agent)
        fprintf_P(stream, agent_fmt, req->req_agent);

    /* Send HTML footer and flush output buffer. */
    fputs_P(foot, stream);
    fflush(stream);

    return 0;
}
Ejemplo n.º 26
0
void ui_header(const char *pstr) {
	lcd_clear();
	
	fputs_P(pstr, lcd);
}
Ejemplo n.º 27
0
// -----------------------------------------------------------------------------
void 
vPrintStr_P (const char * pcStr) {

  fputs_P (pcStr, stdout);
}
Ejemplo n.º 28
0
//------------------------------------------------------------------------------
int StdioStream::printDec(float value, uint8_t prec) {
#define FLOAT_NEW_WAY
#ifdef FLOAT_NEW_WAY
  char buf[24];
  char *ptr = fmtFloat(value, buf + sizeof(buf), prec);
  // return fputs(ptr);
  // uint8_t len = buf + sizeof(buf) - ptr;
  return write(ptr, buf + sizeof(buf) - ptr);
#else
  char* ptr;
  uint8_t rtn = 0;
  uint8_t sign = 0;
  if (value < 0) {
    value = -value;
    sign = '-';
  }
  // check for NaN INF OVF
  if (isnan(value)) {
    if (fputs_P(PSTR("nan")) < 0) {
      return -1;
    }
    rtn += 3;
  } else if (isinf(value)) {
    if (fputs_P(PSTR("inf")) < 0) {
      return -1;
    }
    rtn += 3;
  } else if (value > 4294967040.0) {
    if (fputs_P(PSTR("ovf")) < 0) {
      return -1;
    }
    rtn += 3;
  } else {
    if (sign) {
      if (putc(sign) < 0) {
        return -1;
      }
      rtn++;
    }
    if (prec > 9) {
      prec = 9;
    }

    /*
       uint32_t s = 1;
       for (uint8_t i = 0; i < prec; i++) {
         // s *= 10;
         s = ((s << 2) + s) << 1;
       }
       // round value
       value += 0.5/s;
     */
    value += scale10(0.5, -prec);
    uint32_t whole = value;
    int np;
    if ((np = printDec(whole)) < 0) {
      return -1;
    }
    rtn += np;
    if (prec) {
      if (putc('.') < 0) {
        return -1;
      }
      char* str = fmtSpace(prec);
      if (!str) {
        return -1;
      }
      char* tmp = str - prec;

      //  uint32_t fraction = s*(value - whole);
      uint32_t fraction =  scale10(value - whole, prec);
      ptr = fmtDec(fraction, str);
      while (ptr > tmp) {
        *--ptr = '0';
      }
      rtn += prec + 1;
    }
  }
  return rtn;
#endif
}
Ejemplo n.º 29
0
void ui_loop(void) {
	_ui_init_lcd();
	
	/*alarm_set(1000);*/
	
	char obd_buf[64];
	uint8_t obd_idx = 0;
	
	bool do_cmd = true;
	for ( ; ; ) {
		int c;
		
		/*bool do_cmd = false;
		ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
			if (timer0_count >= 1000) {
				do_cmd = true;
				timer0_count -= 1000;
			}
		}*/
		
		if (do_cmd) {
			// get throttle position
			fputs_P(PSTR("0111\n"), stn1110);
			obd_idx = 0;
			do_cmd = false;
		}
		
		/* repeatedly receive and transmit data until neither are available */
		bool got_data;
		do {
			got_data = false;
			
			/* tx */
			/*if (uart_avail(UART_PC) && (c = fgetc(stdin)) != EOF) {
				fputc(c, stn1110);
				
				if (!tx) {
					tx = true;
					rx = false;
					
					lcd_clear();
					lcd_goto_xy(0, 0);
					fputs_P(PSTR(">>\r\n>>\r\n<<\r\n<<"), lcd);
					lcd_goto_xy(3, 0);
				}
				
				if (c != '\n') {
					fputc(c, lcd);
				}
				
				got_data = true;
			}*/
			
			/* rx */
			if (uart_avail(UART_STN1110) && (c = fgetc(stn1110)) != EOF) {
				fputc(c, stdout);
				
				if (c != '\n') {
					obd_buf[obd_idx++] = c;
				} else {
					obd_buf[obd_idx] = '\0';
					
					/*// REMOVE ME
					strcpy_P(obd_buf, PSTR("10 41 e8"));*/
					
					lcd_clear();
					// TODO: just overwrite
					
					/*static uint8_t counter = 0;*/
					
					uint8_t discard, accel;
					if (sscanf_P(obd_buf, PSTR("%hhx %hhx %hhx"),
						&discard, &discard, &accel)== 3) {
						/*accel = counter++;*/
						
						int16_t accel_i = (int16_t)accel - 40;
						accel_i *= 100;
						accel_i /= (205 - 40);
						
						int16_t accel_b = (accel_i * 4) / 5;
						if (accel_b < 0) accel_b = 0;
						if (accel_b > 100) accel_b = 100;
						
						fprintf_P(lcd, PSTR("%3d"), accel_i);
						fputc(' ', lcd);
						
						while (accel_b >= 5) {
							lcd_write(0xff);
							accel_b -= 5;
						}
						if (accel_b > 0) {
							lcd_write(accel_b - 1);
						}
					} else {
						fprintf_P(lcd, PSTR("error:\r\n%s"), obd_buf);
					}
					
					do_cmd = true;
					
					/*_delay_ms(100);*/
				}
				
				got_data = true;
			}
		} while (got_data);
		
		// TODO: go to sleep instead
		_delay_us(10);
	}
}