From 4b95235843b6e04b15e41ad080e9653bbb49454c Mon Sep 17 00:00:00 2001 From: Stefan `Sec` Zehl Date: Sat, 30 Jul 2011 11:43:08 +0200 Subject: [PATCH 01/13] More serial support --- firmware/SERIAL_DOKU | 14 +++++++++ firmware/applications/serial/serial.c | 43 +++++++++++++++++++-------- 2 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 firmware/SERIAL_DOKU diff --git a/firmware/SERIAL_DOKU b/firmware/SERIAL_DOKU new file mode 100644 index 0000000..4c28ee7 --- /dev/null +++ b/firmware/SERIAL_DOKU @@ -0,0 +1,14 @@ +i: initialize +cb / cm / cr: config funk for beacon/mesh/remote +Ck: set encryptionkey +Ct: set txmac +Cc: set channel +Ct: set rxmac(0) + +s : send packet +s+ : send packet 10 times +sd : send packet with debugoutput + +r: recv packets +r+: recv packets for seconds +r-: recv packets (5 seconds max) diff --git a/firmware/applications/serial/serial.c b/firmware/applications/serial/serial.c index 75c0790..f27dada 100644 --- a/firmware/applications/serial/serial.c +++ b/firmware/applications/serial/serial.c @@ -86,7 +86,7 @@ void dwim(void){ input[inputptr+l]=0; puts_plus(&input[inputptr]); for(int i=0;i0){ + delayms(23); + memcpy(buf,hex,len); + status=nrf_snd_pkt_crc_encr(len,buf,thekey); }; - puts_plus("\r\n"); }else if (input[1]=='t'){ static int ctr=1; int status; From f79f8a93f5ad294f168bbb456c40cc4368136d74 Mon Sep 17 00:00:00 2001 From: Stefan `Sec` Zehl Date: Sat, 30 Jul 2011 11:51:05 +0200 Subject: [PATCH 02/13] Mesh in systick. Now retransmits the time correctly --- firmware/applications/mesh/mesh.c | 92 ++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 33 deletions(-) diff --git a/firmware/applications/mesh/mesh.c b/firmware/applications/mesh/mesh.c index 0ee67e4..dccfd6d 100644 --- a/firmware/applications/mesh/mesh.c +++ b/firmware/applications/mesh/mesh.c @@ -71,7 +71,7 @@ void m_tset(void){ void m_cleanup(void){ time_t now=getSeconds(); - for(int i=0;i_timet) // Do not live in the past. _timet = toff; - lcdPrintln("Got T"); - lcdPrintInt(getSeconds());lcdNl(); - }else if (buf[0]>='A' && buf[0] <'T'){ // Truncate ascii packets. meshbuffer[i].pkt[MESHPKTSIZE-3]=0; }; - lcdRefresh(); }while(getTimer()tm_year+YEAR0); lcdNl(); lcdRefresh(); - delayms(50); + delayms_queue(50); }while ((getInputRaw())==BTN_NONE); }; - -void m_send(void){ - int ctr=0; - __attribute__ ((aligned (4))) uint8_t buf[32]; - int status; - - lcdClear(); - // Update [T]ime packet - - uint32touint8p(getSeconds(),meshbuffer[0].pkt+2); - for (int i=0;i Date: Sat, 30 Jul 2011 15:25:14 +0200 Subject: [PATCH 03/13] Some time related functionality --- firmware/basic/Makefile | 1 + firmware/basic/basic.h | 4 ++++ firmware/basic/simpletime.c | 46 +++++++++++++++++++++++++++++++++++++ firmware/basic/simpletime.h | 16 +++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 firmware/basic/simpletime.c create mode 100644 firmware/basic/simpletime.h diff --git a/firmware/basic/Makefile b/firmware/basic/Makefile index eb3b501..b5dcf51 100644 --- a/firmware/basic/Makefile +++ b/firmware/basic/Makefile @@ -20,6 +20,7 @@ OBJS += random.o OBJS += idle.o OBJS += config.o OBJS += itoa.o +OBJS += simpletime.o LIBNAME=basic diff --git a/firmware/basic/basic.h b/firmware/basic/basic.h index d218cd6..aba4491 100644 --- a/firmware/basic/basic.h +++ b/firmware/basic/basic.h @@ -206,4 +206,8 @@ int applyConfig(void); // itoa.c const char* IntToStrX(unsigned int num, unsigned int mxlen); +// simpletime.c + +#include "basic/simpletime.h" + #endif diff --git a/firmware/basic/simpletime.c b/firmware/basic/simpletime.c new file mode 100644 index 0000000..a43d683 --- /dev/null +++ b/firmware/basic/simpletime.c @@ -0,0 +1,46 @@ +#include +#include "simpletime.h" +#include "basic/basic.h" + +time_t _timet=0; + +int _ytab[2][12] = { + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } +}; + +struct tm * mygmtime(register const time_t time) { + static struct tm br_time; + register struct tm *timep = &br_time; + register unsigned long dayclock, dayno; + int year = EPOCH_YR; + + dayclock = (unsigned long)time % SECS_DAY; + dayno = (unsigned long)time / SECS_DAY; + + timep->tm_sec = dayclock % 60; + timep->tm_min = (dayclock % 3600) / 60; + timep->tm_hour = dayclock / 3600; + timep->tm_wday = (dayno + 4) % 7; /* day 0 was a thursday */ + while (dayno >= YEARSIZE(year)) { + dayno -= YEARSIZE(year); + year++; + } + timep->tm_year = year - YEAR0; + timep->tm_yday = dayno; + timep->tm_mon = 0; + while (dayno >= _ytab[LEAPYEAR(year)][timep->tm_mon]) { + dayno -= _ytab[LEAPYEAR(year)][timep->tm_mon]; + timep->tm_mon++; + } + timep->tm_mday = dayno + 1; + timep->tm_isdst = 0; + + return timep; +} + +// Timezones suck. Currently we only do it all in localtime. +// I know it's broken. Sorry +time_t getSeconds(void){ + return _timet+(getTimer()*SYSTICKSPEED/1000); +}; diff --git a/firmware/basic/simpletime.h b/firmware/basic/simpletime.h new file mode 100644 index 0000000..7efafe5 --- /dev/null +++ b/firmware/basic/simpletime.h @@ -0,0 +1,16 @@ +#ifndef __SIMPLETIME_H_ +#define __SIMPLETIME_H_ + +#include + +#define YEAR0 1900 /* the first year */ +#define EPOCH_YR 1970 /* EPOCH = Jan 1 1970 00:00:00 */ +#define SECS_DAY (24L * 60L * 60L) +#define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400))) +#define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365) + +extern time_t _timet; +struct tm * mygmtime(register const time_t time); +time_t getSeconds(void); + +#endif From 1077b5fd1e2e255bdc0feb140b7a804963c74853 Mon Sep 17 00:00:00 2001 From: Stefan `Sec` Zehl Date: Sat, 30 Jul 2011 15:30:35 +0200 Subject: [PATCH 04/13] Fix filename to be the same in read && write --- firmware/funk/openbeacon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/funk/openbeacon.c b/firmware/funk/openbeacon.c index 599af98..8fdf946 100644 --- a/firmware/funk/openbeacon.c +++ b/firmware/funk/openbeacon.c @@ -32,7 +32,7 @@ void openbeaconSave(uint32_t s) BYTE buf[4]; UINT readbytes; - if( f_open(&file, "beacon", FA_OPEN_ALWAYS|FA_WRITE) ) + if( f_open(&file, "beacon.cfg", FA_OPEN_ALWAYS|FA_WRITE) ) return; uint32touint8p(s, buf); From 1a23641c8dce920304c15658b386335333e15b95 Mon Sep 17 00:00:00 2001 From: Stefan `Sec` Zehl Date: Sat, 30 Jul 2011 16:10:30 +0200 Subject: [PATCH 05/13] Refactor mesh stuff --- firmware/applications/mesh/mesh.c | 232 +++++++----------------------- firmware/funk/Makefile | 1 + firmware/funk/mesh.c | 163 +++++++++++++++++++++ firmware/funk/mesh.h | 38 +++++ 4 files changed, 250 insertions(+), 184 deletions(-) create mode 100644 firmware/funk/mesh.c create mode 100644 firmware/funk/mesh.h diff --git a/firmware/applications/mesh/mesh.c b/firmware/applications/mesh/mesh.c index dccfd6d..e142c50 100644 --- a/firmware/applications/mesh/mesh.c +++ b/firmware/applications/mesh/mesh.c @@ -10,39 +10,12 @@ #include "funk/nrf24l01p.h" +#include "funk/mesh.h" + #include -#define MESH_CHANNEL 85 -#define MESH_MAC "MESHB" - /**************************************************************************/ -uint32_t const meshkey[4] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000 -}; - -#define MESHBUFSIZE 10 -#define MESHPKTSIZE 32 -typedef struct { - uint8_t pkt[32]; - char flags; -} MPKT; - -MPKT meshbuffer[MESHBUFSIZE]; - -#define MF_FREE (0) -#define MF_USED (1<<0) - -time_t _timet=0; - -// Timezones suck. Currently we only do it all in localtime. -// I know it's broken. Sorry -time_t getSeconds(void){ - return _timet+(getTimer()*SYSTICKSPEED/1000); -}; - -// ********************************************************************** - void m_init(void){ nrf_init(); @@ -56,169 +29,16 @@ void m_init(void){ nrf_config_set(&config); - for(int i=0;itm_sec = dayclock % 60; - timep->tm_min = (dayclock % 3600) / 60; - timep->tm_hour = dayclock / 3600; - timep->tm_wday = (dayno + 4) % 7; /* day 0 was a thursday */ - while (dayno >= YEARSIZE(year)) { - dayno -= YEARSIZE(year); - year++; - } - timep->tm_year = year - YEAR0; - timep->tm_yday = dayno; - timep->tm_mon = 0; - while (dayno >= _ytab[LEAPYEAR(year)][timep->tm_mon]) { - dayno -= _ytab[LEAPYEAR(year)][timep->tm_mon]; - timep->tm_mon++; - } - timep->tm_mday = dayno + 1; - timep->tm_isdst = 0; - - return timep; -} - -#define M_SENDINT 500 -#define M_RECVINT 1000 -#define M_RECVTIM 100 - - -void m_recv(void){ - __attribute__ ((aligned (4))) uint8_t buf[32]; - int len; - int recvend=M_RECVTIM/SYSTICKSPEED+getTimer(); - - static int toggle=0; - gpioSetValue (RB_LED2, toggle); - toggle=1-toggle; - - m_cleanup(); - - nrf_rcv_pkt_start(); - do{ - len=nrf_rcv_pkt_poll_dec(sizeof(buf),buf,meshkey); - - // Receive - if(len<=0){ - delayms_power(10); - continue; - }; - - int i; - for(i=0;i_timet) // Do not live in the past. - _timet = toff; - }else if (buf[0]>='A' && buf[0] <'T'){ // Truncate ascii packets. - meshbuffer[i].pkt[MESHPKTSIZE-3]=0; - }; - }while(getTimer()tm_year+YEAR0); lcdNl(); + + lcdNl(); + lcdPrint("<"); + + for(int i=0;i"); + + lcdPrint("Gen:"); + lcdPrintInt(meshgen); + lcdNl(); lcdRefresh(); delayms_queue(50); }while ((getInputRaw())==BTN_NONE); }; + + +inline void blink(char a, char b){ + gpioSetValue (a,b, 1-gpioGetValue(a,b)); +}; + + + +/***********************************************************************/ + + +void m_cleanup(void){ + mesh_cleanup(); +}; + +void m_recv(void){ + mesh_recvloop(); +} + +void m_send(void){ + mesh_sendloop(); +}; + +void tick_mesh(void){ + mesh_systick(); +}; + diff --git a/firmware/funk/Makefile b/firmware/funk/Makefile index 77e9a83..b8bd41f 100644 --- a/firmware/funk/Makefile +++ b/firmware/funk/Makefile @@ -8,6 +8,7 @@ OBJS += nrf24l01p.o OBJS += rftransfer.o OBJS += filetransfer.o OBJS += openbeacon.o +OBJS += mesh.o LIBNAME=funk diff --git a/firmware/funk/mesh.c b/firmware/funk/mesh.c new file mode 100644 index 0000000..e0f869f --- /dev/null +++ b/firmware/funk/mesh.c @@ -0,0 +1,163 @@ +#include +#include +#include "basic/basic.h" +#include "funk/mesh.h" +#include "funk/nrf24l01p.h" +#include "basic/byteorder.h" +#include "basic/random.h" + +char meshgen=0; // Generation +MPKT meshbuffer[MESHBUFSIZE]; + +uint32_t const meshkey[4] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +struct NRF_CFG oldconfig; + +void initMesh(void){ + for(int i=0;iSECS_DAY) + meshbuffer[i].flags=MF_FREE; + }; + }; +}; + +void mesh_recvloop(void){ + __attribute__ ((aligned (4))) uint8_t buf[32]; + int len; + int recvend=M_RECVTIM/SYSTICKSPEED+getTimer(); + int pktctr=0; + + nrf_config_get(&oldconfig); + + nrf_set_channel(MESH_CHANNEL); + nrf_set_rx_mac(0,MESHPKTSIZE,strlen(MESH_MAC),(uint8_t*)MESH_MAC); + + mesh_cleanup(); + + nrf_rcv_pkt_start(); + do{ + len=nrf_rcv_pkt_poll_dec(sizeof(buf),buf,meshkey); + + // Receive + if(len<=0){ + delayms_power(10); + continue; + }; + pktctr++; + + if(MO_GEN(buf)>meshgen){ + meshgen++; + _timet=0; + continue; + }; + + if(MO_TYPE(buf)=='T'){ + time_t toff=MO_TIME(buf)-(getTimer()*SYSTICKSPEED/1000); + if (toff>_timet) // Do not live in the past. + _timet = toff; + continue; + }; + + // Safety: Truncate ascii packets by 0-ing the CRC + if (MO_TYPE(buf) >='A' && MO_TYPE(buf) <='Z'){ + buf[MESHPKTSIZE-2]=0; + }; + + // Store packet in a free slot + int free=-1; + for(int i=0;i + MO_TIME(meshbuffer[i].pkt)){ + free=i; + break; + }else{ + free=-2; + break; + }; + }; + }; + + if(free==-1){ // Buffer full. Ah well. Kill a random packet + free=1; // XXX: GetRandom()? + }; + + if(free<0) + continue; + + memcpy(meshbuffer[free].pkt,buf,MESHPKTSIZE); + meshbuffer[free].flags=MF_USED; + + }while(getTimer()MESHBUFSIZE); + + nrf_rcv_pkt_end(); + nrf_config_set(&oldconfig); +} + +void mesh_sendloop(void){ + int ctr=0; + __attribute__ ((aligned (4))) uint8_t buf[32]; + int status; + + nrf_config_get(&oldconfig); + nrf_set_channel(MESH_CHANNEL); + nrf_set_tx_mac(strlen(MESH_MAC),(uint8_t*)MESH_MAC); + + // Update [T]ime packet + MO_TIME_set(meshbuffer[0].pkt,getSeconds()); + MO_GEN_set(meshbuffer[0].pkt,meshgen); + + for (int i=0;i Date: Sat, 30 Jul 2011 19:06:12 +0200 Subject: [PATCH 06/13] Mesh++ Now we can display messages. --- firmware/applications/mesh/mesh.c | 184 ++++++++++++++++++++++++++++-- firmware/funk/mesh.h | 1 + 2 files changed, 178 insertions(+), 7 deletions(-) diff --git a/firmware/applications/mesh/mesh.c b/firmware/applications/mesh/mesh.c index e142c50..c1f2f1c 100644 --- a/firmware/applications/mesh/mesh.c +++ b/firmware/applications/mesh/mesh.c @@ -84,22 +84,192 @@ inline void blink(char a, char b){ }; +int choose(char * texts, int8_t menuselection){ + uint8_t numentries = 0; + uint8_t visible_lines = 0; + uint8_t current_offset = 0; + + char*p=texts; + + do{ + lcdPrintln(p); + while(*p)p++; + numentries++;p++; + }while(*p); + numentries--; + + visible_lines = (RESY/font->u8Height)-1; // subtract title line + + while (1) { + // Display current menu page + lcdClear(); + lcdPrintln(texts); + p=texts; + while(*p++); + for(int i=0;i (current_offset + visible_lines-1) || menuselection >= numentries) { + if (menuselection >= numentries) { + menuselection = 0; + current_offset = 0; + } else { + current_offset += visible_lines; + } + } + break; + case BTN_LEFT: + return -1; + case BTN_RIGHT: + case BTN_ENTER: + return menuselection; + } + getInputWaitRelease(); + } + /* NOTREACHED */ +} + + /***********************************************************************/ +char *meshmsgs(void){ + static char msgtypes[MESHBUFSIZE+1]; + memset(msgtypes,'_',MESHBUFSIZE); + msgtypes[MESHBUFSIZE]=0; + uint8_t lo=0; + uint8_t hi; -void m_cleanup(void){ - mesh_cleanup(); + for(int o=0;olo) + if(MO_TYPE(meshbuffer[i].pkt)tm_hour); + lcdPrint(":"); + lcdPrintInt(tm->tm_min); + lcdPrint(":"); + lcdPrintInt(tm->tm_sec); + lcdNl(); + char *foo=(char *)MO_BODY(meshbuffer[j].pkt); + while(strlen(foo)>13){ + int q; + for(q=0;q<13;q++){ + if(foo[q]==' ') + break; + }; + foo[q]=0; + lcdPrintln(foo); + foo[q]=' '; + foo+=q+1; + }; + lcdPrintln(foo); + lcdRefresh(); + getInputWaitRelease(); + }; }; + void tick_mesh(void){ mesh_systick(); }; diff --git a/firmware/funk/mesh.h b/firmware/funk/mesh.h index b9555a2..7bbe2cf 100644 --- a/firmware/funk/mesh.h +++ b/firmware/funk/mesh.h @@ -17,6 +17,7 @@ #define MO_GEN_set(x,y) (x[1]=y) #define MO_TIME(x) (uint8ptouint32(x+2)) #define MO_TIME_set(x,y) (uint32touint8p(y,x+2)) +#define MO_BODY(x) (x+6) typedef struct { uint8_t pkt[32]; From d8cbdc79fa21a70eaa8c42fb43a9a75d59b70fd3 Mon Sep 17 00:00:00 2001 From: iggy Date: Sat, 30 Jul 2011 19:28:37 +0200 Subject: [PATCH 07/13] string input + demo --- firmware/applications/inputtest.c | 29 ++++++++ firmware/basic/Makefile | 1 + firmware/basic/basic.h | 2 + firmware/basic/stringin.c | 107 ++++++++++++++++++++++++++++++ 4 files changed, 139 insertions(+) create mode 100644 firmware/applications/inputtest.c create mode 100644 firmware/basic/stringin.c diff --git a/firmware/applications/inputtest.c b/firmware/applications/inputtest.c new file mode 100644 index 0000000..0512abe --- /dev/null +++ b/firmware/applications/inputtest.c @@ -0,0 +1,29 @@ +#include + +#include "basic/basic.h" +#include "lcd/render.h" +#include "lcd/display.h" +#include "lcd/allfonts.h" + +#define CHARWIDTH 12 +#define CHARSPACE 0x20 + +void main_inputtest(void) { + backlightInit(); + + char nick[20]; + memset(nick,0,20); + strcpy(nick,"iggy"); + + while(1) { + input("Nick?", nick, 0x20, 0x7f, 20); + + lcdFill(0); + font=&Font_Orbitron14pt; + DoString(20,20,nick); + lcdDisplay(); + + while(getInput() != BTN_ENTER){} + } +} + diff --git a/firmware/basic/Makefile b/firmware/basic/Makefile index eb3b501..5f772fd 100644 --- a/firmware/basic/Makefile +++ b/firmware/basic/Makefile @@ -20,6 +20,7 @@ OBJS += random.o OBJS += idle.o OBJS += config.o OBJS += itoa.o +OBJS += stringin.o LIBNAME=basic diff --git a/firmware/basic/basic.h b/firmware/basic/basic.h index d218cd6..ec82179 100644 --- a/firmware/basic/basic.h +++ b/firmware/basic/basic.h @@ -153,6 +153,8 @@ uint8_t getInputRaw(void); uint8_t getInputWait(void); void getInputWaitRelease(void); +// stringin.c +void input(char prompt[], char line[], uint8_t asciistart, uint8_t asciiend, uint8_t maxlength); //uuid.c #include "basic/uuid.h" diff --git a/firmware/basic/stringin.c b/firmware/basic/stringin.c new file mode 100644 index 0000000..20e72bb --- /dev/null +++ b/firmware/basic/stringin.c @@ -0,0 +1,107 @@ + +#include "basic/basic.h" +#include "lcd/render.h" +#include "lcd/display.h" +#include "lcd/allfonts.h" + +#define CHARWIDTH 12 +#define CHARSPACE 0x20 + +struct in{ + char *line, *prompt; + uint8_t pos, dcursor, maxlength, asciistart, asciiend; + bool done; +} s_input; + +void inputInit(char p[],char s[], uint8_t l, uint8_t as, uint8_t ae) { + //TODO: Check length! + s_input.prompt = p; + s_input.line = s; + s_input.maxlength = l; + s_input.asciistart = as; + s_input.asciiend = ae; + s_input.pos = 0; + s_input.dcursor = 0; + s_input.done = false; +} + + +void inputMove() { + char *cur = s_input.line+s_input.pos+s_input.dcursor; + char key = getInput(); + if (key == BTN_LEFT) { + if (s_input.dcursor >0) { + s_input.dcursor --; + } else if (s_input.pos > 0) { + s_input.pos --; + } + } else if (key == BTN_RIGHT) { + if (s_input.dcursor s_input.asciiend) { + *cur = s_input.asciiend; + } else { + *cur = *cur - 1; + } + } else if (key == BTN_UP) { + if (*cur >= s_input.asciiend) { + *cur = s_input.asciistart; + } else if (*cur < s_input.asciistart) { + *cur = s_input.asciistart; + } else { + *cur = *cur + 1; + } + } else if (key == (BTN_ENTER)) { + s_input.done = true; + } +} + +void inputDraw() { + lcdFill(0); + DoString(0,0,s_input.prompt); + for (int dx = 0; dx<= RESX/CHARWIDTH && s_input.pos+dx=0) { + s_input.line[x] = 0; + x--; + } + return; + } + } +} + +void input(char prompt[], char line[], uint8_t asciistart, uint8_t asciiend, uint8_t maxlength){ + font=&Font_7x8; + inputInit(prompt, line, maxlength, asciistart, asciiend); + lcdFill(0); + while (!s_input.done) { + lcdDisplay(); + inputMove(); + inputDraw(); + } + inputClean(); + return; +} + From 06ac802ee5187d5c3b0e97733f01cdcf359659a9 Mon Sep 17 00:00:00 2001 From: Stefan `Sec` Zehl Date: Sun, 31 Jul 2011 00:53:14 +0200 Subject: [PATCH 08/13] More abstracted num to string functions --- firmware/basic/basic.h | 5 +++++ firmware/basic/itoa.c | 47 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/firmware/basic/basic.h b/firmware/basic/basic.h index 185c9ed..c4ec7bb 100644 --- a/firmware/basic/basic.h +++ b/firmware/basic/basic.h @@ -206,7 +206,12 @@ int applyConfig(void); #define SYSTICKSPEED 10 // itoa.c +#define F_ZEROS (1<<0) +#define F_LONG (1<<1) +#define F_SPLUS (1<<2) +#define F_SSPACE (1<<3) const char* IntToStrX(unsigned int num, unsigned int mxlen); +const char* IntToStr(int num, unsigned int mxlen, char flag); // simpletime.c diff --git a/firmware/basic/itoa.c b/firmware/basic/itoa.c index 9cc8de5..abaef8f 100644 --- a/firmware/basic/itoa.c +++ b/firmware/basic/itoa.c @@ -1,8 +1,8 @@ -#define LEN 32 +#include "basic/basic.h" +#define LEN 10 const char* IntToStrX(unsigned int num, unsigned int mxlen){ static char s[LEN+1]; - char * o=s; int len; s[LEN]=0; for (len=(LEN-1);len>=(LEN-mxlen);len--){ @@ -13,3 +13,46 @@ const char* IntToStrX(unsigned int num, unsigned int mxlen){ }; return &s[len+1]; }; +#undef LEN + +#define LEN 11 +const char* IntToStr(int num, unsigned int mxlen, char flag){ + static char s[LEN+1]; + int len; + s[LEN]=0; + char neg=0; + + if(num<0){ + num=-num; + neg=1; + }; + + for (len=(LEN-1);len>=(LEN-mxlen);len--){ + s[len]=(num%10)+'0'; + num/=10; + }; + len++; + + if(!(flag&F_LONG)){ + while(s[len]=='0' && len < (LEN-1)) + len++; + }else if(!(flag&F_ZEROS)){ + int x=len; + while(s[x]=='0' && x < (LEN-1)){ + s[x]=' '; + x++; + }; + } + + if(neg==1){ + len--; + s[len]='-'; + }else if(flag&F_SPLUS){ + len--; + s[len]='+'; + }else if(flag&F_SSPACE){ + s[len]=' '; + }; + return &s[len]; +}; +#undef LEN From 8bc5424607113af4f636c8ede275bf6763f70640 Mon Sep 17 00:00:00 2001 From: Stefan `Sec` Zehl Date: Sun, 31 Jul 2011 00:53:53 +0200 Subject: [PATCH 09/13] Fix time and generation handling a bit --- firmware/funk/mesh.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/firmware/funk/mesh.c b/firmware/funk/mesh.c index e0f869f..4928cae 100644 --- a/firmware/funk/mesh.c +++ b/firmware/funk/mesh.c @@ -68,13 +68,15 @@ void mesh_recvloop(void){ pktctr++; if(MO_GEN(buf)>meshgen){ - meshgen++; + if(meshgen) + meshgen++; + else + meshgen=MO_GEN(buf); _timet=0; - continue; }; if(MO_TYPE(buf)=='T'){ - time_t toff=MO_TIME(buf)-(getTimer()*SYSTICKSPEED/1000); + time_t toff=MO_TIME(buf)-((getTimer()-(200/SYSTICKSPEED))/(1000/SYSTICKSPEED)); if (toff>_timet) // Do not live in the past. _timet = toff; continue; From a20a260117752d78ddc82e6d379c9cc02112334d Mon Sep 17 00:00:00 2001 From: Stefan `Sec` Zehl Date: Sun, 31 Jul 2011 00:54:41 +0200 Subject: [PATCH 10/13] Show badge uptime --- firmware/applications/mesh/util.c | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/firmware/applications/mesh/util.c b/firmware/applications/mesh/util.c index 8747264..a19dc71 100644 --- a/firmware/applications/mesh/util.c +++ b/firmware/applications/mesh/util.c @@ -44,6 +44,39 @@ void adc_light(void) { dx=DoString(0,dy,"Done."); }; +void uptime(void) { + int t; + int h; + char flag; + while ((getInputRaw())==BTN_NONE){ + lcdClear(); + lcdPrintln("Uptime:"); + t=getTimer()/(1000/SYSTICKSPEED); + h=t/60/60; + flag=F_ZEROS; + if(h>0){ + lcdPrint(IntToStr(h,2,flag)); + lcdPrint("h"); + flag|=F_LONG; + }; + h=t/60%60; + if(h>0){ + lcdPrint(IntToStr(h,2,flag)); + lcdPrint("m"); + flag|=F_LONG; + }; + h=t%60; + if(h>0){ + lcdPrint(IntToStr(h,2,flag)); + lcdPrint("s"); + }; + lcdNl(); + lcdRefresh(); + delayms_queue(200); + }; + lcdPrintln("done."); +}; + void gotoISP(void) { DoString(0,0,"Enter ISP!"); lcdDisplay(); From 2c62859a6012b3dada720e7b2e3e558546110f9e Mon Sep 17 00:00:00 2001 From: Stefan `Sec` Zehl Date: Sun, 31 Jul 2011 00:55:02 +0200 Subject: [PATCH 11/13] more pretty-printing --- firmware/applications/mesh/mesh.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/firmware/applications/mesh/mesh.c b/firmware/applications/mesh/mesh.c index c1f2f1c..deb1657 100644 --- a/firmware/applications/mesh/mesh.c +++ b/firmware/applications/mesh/mesh.c @@ -44,17 +44,17 @@ void m_time(void){ do{ lcdClear(); tm= mygmtime(getSeconds()); - lcdPrintInt(tm->tm_hour); + lcdPrint(IntToStr(tm->tm_hour,2,F_LONG)); lcdPrint(":"); - lcdPrintInt(tm->tm_min); + lcdPrint(IntToStr(tm->tm_min,2,F_LONG|F_ZEROS)); lcdPrint(":"); - lcdPrintInt(tm->tm_sec); + lcdPrint(IntToStr(tm->tm_sec,2,F_LONG|F_ZEROS)); lcdNl(); - lcdPrintInt(tm->tm_mday); + lcdPrint(IntToStr(tm->tm_mday,2,F_LONG)); lcdPrint("."); - lcdPrintInt(tm->tm_mon+1); + lcdPrint(IntToStr(tm->tm_mon+1,2,0)); lcdPrint("."); - lcdPrintInt(tm->tm_year+YEAR0); + lcdPrint(IntToStr(tm->tm_year+YEAR0,4,F_LONG|F_ZEROS)); lcdNl(); lcdNl(); @@ -245,11 +245,11 @@ void m_choose(){ break; }; struct tm *tm= mygmtime(MO_TIME(meshbuffer[j].pkt)); - lcdPrintInt(tm->tm_hour); + lcdPrint(IntToStr(tm->tm_hour,2,F_LONG)); lcdPrint(":"); - lcdPrintInt(tm->tm_min); + lcdPrint(IntToStr(tm->tm_min,2,F_LONG|F_ZEROS)); lcdPrint(":"); - lcdPrintInt(tm->tm_sec); + lcdPrint(IntToStr(tm->tm_sec,2,F_LONG|F_ZEROS)); lcdNl(); char *foo=(char *)MO_BODY(meshbuffer[j].pkt); while(strlen(foo)>13){ From cfe6e328e5754468ca1da56449471ee9fb616d99 Mon Sep 17 00:00:00 2001 From: Stefan `Sec` Zehl Date: Sun, 31 Jul 2011 18:15:44 +0200 Subject: [PATCH 12/13] You will probably hate me, but commit new, global config framework hopefully it will be stable now. Sorry for breaking your stuff --- firmware/applications/default.c | 15 +++++-- firmware/basic/basic.h | 36 ++++++++++------- firmware/basic/config.c | 69 +++++++++++++++++++++------------ firmware/basic/night.c | 4 +- firmware/lcd/display.c | 36 +++++++++++++---- firmware/lcd/display.h | 1 + firmware/lcd/render.c | 6 +++ firmware/lcd/render.h | 1 + 8 files changed, 117 insertions(+), 51 deletions(-) diff --git a/firmware/applications/default.c b/firmware/applications/default.c index 4e145ee..d4f0b00 100644 --- a/firmware/applications/default.c +++ b/firmware/applications/default.c @@ -38,10 +38,17 @@ void tick_default(void) { }; }; - if(isNight()) - backlightSetBrightness(globalconfig.backlightvalue); - else - backlightSetBrightness(0); + if(ctr>100/SYSTICKSPEED){ + if(isNight()){ + backlightSetBrightness(GLOBAL(lcdbacklight)); + if(GLOBAL(nightinvert)) + lcdSetInvert(0); + } else { + backlightSetBrightness(0); + if(GLOBAL(nightinvert)) + lcdSetInvert(1); + } + } if(ctr%(50/SYSTICKSPEED)==0){ diff --git a/firmware/basic/basic.h b/firmware/basic/basic.h index c4ec7bb..41ed5c7 100644 --- a/firmware/basic/basic.h +++ b/firmware/basic/basic.h @@ -187,21 +187,31 @@ void handleMenu(const struct MENU *the_menu); // config.c -struct config_t { - time_t time; - uint16_t backlighttrigger; - char backlightvalue; - char lcdstate; - char privacy; -} __attribute__((__packed__)); - -typedef struct config_t CONFIG; - -extern CONFIG globalconfig; - int readConfig(void); int saveConfig(void); -int applyConfig(void); +void applyConfig(void); + + +struct CDESC { + char *name; + char value; + char min; + char max; +}; + +extern struct CDESC the_config[]; + +#define GLOBALversion (the_config[0].value) +#define GLOBALprivacy (the_config[1].value) +#define GLOBALnighttrigger (the_config[2].value) +#define GLOBALnightinvert (the_config[3].value) +#define GLOBALlcdbacklight (the_config[4].value) +#define GLOBALlcdmirror (the_config[5].value) +#define GLOBALlcdinvert (the_config[6].value) +#define GLOBALlcdcontrast (the_config[7].value) + +#define GLOBAL(x) GLOBAL ## x + #define SYSTICKSPEED 10 diff --git a/firmware/basic/config.c b/firmware/basic/config.c index eea1936..d4a0b5a 100644 --- a/firmware/basic/config.c +++ b/firmware/basic/config.c @@ -1,21 +1,38 @@ #include #include "basic/basic.h" -#include "lcd/lcd.h" -#include "lcd/fonts/smallfonts.h" #include "lcd/print.h" #include "filesystem/ff.h" #include "basic/random.h" -CONFIG globalconfig = { 0,310,50,0,0}; +#define CFGVER 23 + +struct CDESC the_config[]= { + {"version", CFGVER, CFGVER, CFGVER}, + {"privacy", 3, 0, 2 }, + {"nighttrigger", 310/2, 0, 255}, + {"nightinvert", 1, 0, 1 }, + {"lcdbacklight", 50, 0, 100}, + {"lcdmirror", 0, 0, 1 }, + {"lcdinvert", 0, 0, 1 }, + {"lcdcontrast", 3, 1, 6 }, + { NULL, 0, 0, 0 }, +}; #define CONFFILE "r0ket.cfg" +#define CONF_ITER for(int i=0;the_config[i].name!=NULL;i++) /**************************************************************************/ +void applyConfig(){ + lcdSetContrast(GLOBAL(lcdcontrast)); + return 0; +}; + int saveConfig(void){ FIL file; /* File object */ UINT writebytes; + UINT allwrite=0; int res; res=f_open(&file, CONFFILE, FA_OPEN_ALWAYS|FA_WRITE); @@ -25,16 +42,20 @@ int saveConfig(void){ return 1; }; - res = f_write(&file, &globalconfig, sizeof(CONFIG), &writebytes); + CONF_ITER{ + res = f_write(&file, &the_config[i].value, sizeof(uint8_t), &writebytes); + allwrite+=writebytes; + if(res){ + lcdPrint("write:"); + lcdPrintln(f_get_rc_string(res)); + return 1; + }; + }; lcdPrint("write:"); lcdPrintln(f_get_rc_string(res)); - if(res){ - return 1; - }; - - lcdPrint("wrote:"); - lcdPrintInt(writebytes); - lcdPrintln("b"); + lcdPrint(" ("); + lcdPrintInt(allwrite); + lcdPrintln("b)"); res=f_close(&file); lcdPrint("close:"); @@ -48,34 +69,32 @@ int saveConfig(void){ int readConfig(void){ FIL file; /* File object */ UINT readbytes; + UINT allread; int res; - lcdFill(0); // clear display buffer - res=f_open(&file, CONFFILE, FA_OPEN_EXISTING|FA_READ); - lcdPrint("open:"); - lcdPrintln(f_get_rc_string(res)); if(res){ return 1; }; - res = f_read(&file, &globalconfig, sizeof(CONFIG), &readbytes); - lcdPrint("read:"); - lcdPrintln(f_get_rc_string(res)); - if(res){ - return 1; + CONF_ITER{ + res = f_read(&file, &the_config[i].value, sizeof(uint8_t), &readbytes); + allread+=readbytes; + if(GLOBAL(version) != CFGVER){ + GLOBAL(version) =CFGVER; + return 1; + }; + if(res || GLOBAL(version) != CFGVER) + return 1; }; res=f_close(&file); - lcdPrint("close:"); - lcdPrintln(f_get_rc_string(res)); if(res){ return 1; }; + + applyConfig(); return 0; }; -int applyConfig(){ - return 0; -}; diff --git a/firmware/basic/night.c b/firmware/basic/night.c index 6110818..ae62db1 100644 --- a/firmware/basic/night.c +++ b/firmware/basic/night.c @@ -7,7 +7,7 @@ uint32_t light=300*HYST; char _isnight=1; -#define threshold globalconfig.backlighttrigger +#define threshold GLOBAL(nighttrigger) void LightCheck(void){ int iocon; @@ -22,7 +22,7 @@ void LightCheck(void){ gpioSetDir(RB_LED3, gpioDirection_Input); IOCON_PIO1_11 = IOCON_PIO1_11_FUNC_AD7|IOCON_PIO1_11_ADMODE_ANALOG; light-=light/HYST; - light += adcRead(7); + light += (adcRead(7)/2); gpioSetDir(RB_LED3, iodir); IOCON_PIO1_11=iocon; diff --git a/firmware/lcd/display.c b/firmware/lcd/display.c index 06b61f5..3ffd916 100644 --- a/firmware/lcd/display.c +++ b/firmware/lcd/display.c @@ -13,7 +13,6 @@ /**************************************************************************/ uint8_t lcdBuffer[RESX*RESY_B]; -#define lcd_layout globalconfig.lcdstate uint32_t intstatus; // Caches USB interrupt state // (need to disable MSC while displaying) @@ -153,12 +152,12 @@ void lcdDisplay(void) { uint16_t i,page; for(page=0; page0x2e) c=0x24; + lcd_select(); + lcdWrite(TYPE_CMD,c); + lcd_deselect(); +}; +void lcdSetInvert(int c) { + if(c>1) + c=1; + if(c<0) + c=1; + + c+=0xa6; + lcd_select(); + lcdWrite(TYPE_CMD,c); + lcd_deselect(); +}; + +/* deprecated */ +void __attribute__((__deprecated__)) lcdToggleFlag(int flag) { + if(flag==LCD_MIRRORX) + GLOBAL(lcdmirror)=!GLOBAL(lcdmirror); + if(flag==LCD_INVERTED) + GLOBAL(lcdinvert)=!GLOBAL(lcdinvert); +} void lcdShiftH(bool right, bool wrap) { diff --git a/firmware/lcd/display.h b/firmware/lcd/display.h index 5d92540..79f671e 100644 --- a/firmware/lcd/display.h +++ b/firmware/lcd/display.h @@ -29,4 +29,5 @@ void lcdSetPixel(char x, char y, bool f); void lcdSafeSetPixel(char x, char y, bool f); bool lcdGetPixel(char x, char y); void lcdShift(int x, int y, bool wrap); +void lcdSetContrast(int c); #endif diff --git a/firmware/lcd/render.c b/firmware/lcd/render.c index 8355dd0..62339df 100644 --- a/firmware/lcd/render.c +++ b/firmware/lcd/render.c @@ -34,6 +34,12 @@ void setExtFont(const char *fname){ font=NULL; }; +int getFontHeight(void){ + if(font) + return font->u8Height; + return 8; // XXX: Should be done right. +}; + int _getFontData(int type, int offset){ UINT readbytes; diff --git a/firmware/lcd/render.h b/firmware/lcd/render.h index eaa69ef..e78975c 100644 --- a/firmware/lcd/render.h +++ b/firmware/lcd/render.h @@ -36,6 +36,7 @@ int DoCharX(int sx, int sy, unsigned char num); int DoShortX(int sx, int sy, uint16_t num); void setIntFont(const struct FONT_DEF * font); void setExtFont(const char *file); +int getFontHeight(void); #define START_FONT 0 #define SEEK_EXTRAS 1 From e3d46f01bd2e18084af539617878fdfea4ab8c2d Mon Sep 17 00:00:00 2001 From: Stefan `Sec` Zehl Date: Sun, 31 Jul 2011 18:20:55 +0200 Subject: [PATCH 13/13] Fix a few global config regressions, and add sample config menu --- firmware/applications/mesh/config.c | 110 +++++++++++++++++++++++--- firmware/applications/mesh/util.c | 2 +- firmware/applications/tester/config.c | 38 --------- firmware/applications/tester/util.c | 35 +++++++- 4 files changed, 133 insertions(+), 52 deletions(-) delete mode 100644 firmware/applications/tester/config.c diff --git a/firmware/applications/mesh/config.c b/firmware/applications/mesh/config.c index 0d8df7c..4343198 100644 --- a/firmware/applications/mesh/config.c +++ b/firmware/applications/mesh/config.c @@ -23,16 +23,102 @@ void applycfg(void){ applyConfig(); }; -void show(void){ - lcdClear(); - lcdPrint("time:"); lcdPrintInt(globalconfig.time); lcdNl(); - lcdPrint("btrig:"); lcdPrintInt(globalconfig.backlighttrigger); lcdNl(); - lcdPrint("bval:"); lcdPrintInt(globalconfig.backlightvalue); lcdNl(); - lcdPrint("lcd:"); lcdPrintInt(globalconfig.lcdstate); lcdNl(); - lcdPrint("priv:"); lcdPrintInt(globalconfig.privacy); lcdNl(); - lcdRefresh(); -}; +void changer(void){ + uint8_t numentries = 0; + signed char menuselection = 0; + uint8_t visible_lines = 0; + uint8_t current_offset = 0; -void lcdmirror(void){ - lcdToggleFlag(LCD_MIRRORX); -}; + for (int i=0;the_config[i].name!=NULL;i++){ + numentries++; + }; + + visible_lines = ((RESY/getFontHeight())-1)/2; + + while (1) { + // Display current menu page + lcdClear(); + lcdPrint("Config"); + + lcdSetCrsrX(60); + lcdPrint("["); + lcdPrint(IntToStr(current_offset/visible_lines,1,0)); + lcdPrint("/"); + lcdPrint(IntToStr(numentries/visible_lines,1,0)); + lcdPrint("]"); + lcdNl(); + + lcdNl(); + + for (uint8_t i = current_offset; i < (visible_lines + current_offset) && i < numentries; i++) { + if(i==0){ + lcdPrintln("Save changes:"); + if (i == menuselection) + lcdPrint("*"); + lcdSetCrsrX(14); + if (i == menuselection) + lcdPrintln("YES"); + else + lcdPrintln("no"); + }else{ + lcdPrintln(the_config[i].name); + if (i == menuselection) + lcdPrint("*"); + lcdSetCrsrX(14); + lcdPrint("<"); + lcdPrint(IntToStr(the_config[i].value,3,F_LONG)); + lcdPrintln(">"); + }; + } + lcdRefresh(); + + switch (getInputWait()) { + case BTN_UP: + menuselection--; + if (menuselection < current_offset) { + if (menuselection < 0) { + menuselection = numentries-1; + current_offset = ((numentries-1)/visible_lines) * visible_lines; + } else { + current_offset -= visible_lines; + } + } + break; + case BTN_DOWN: + menuselection++; + if (menuselection > (current_offset + visible_lines-1) || menuselection >= numentries) { + if (menuselection >= numentries) { + menuselection = 0; + current_offset = 0; + } else { + current_offset += visible_lines; + } + } + break; + case BTN_LEFT: + if(the_config[menuselection].value > + the_config[menuselection].min) + the_config[menuselection].value--; + if(the_config[menuselection].value > the_config[menuselection].max) + the_config[menuselection].value= + the_config[menuselection].max; + applyConfig(); + break; + case BTN_RIGHT: + if(the_config[menuselection].value < + the_config[menuselection].max) + the_config[menuselection].value++; + if(the_config[menuselection].value < the_config[menuselection].min) + the_config[menuselection].value= + the_config[menuselection].min; + applyConfig(); + break; + case BTN_ENTER: + if(menuselection==0) + saveConfig(); + return; + } + getInputWaitRelease(); + } + /* NOTREACHED */ +} diff --git a/firmware/applications/mesh/util.c b/firmware/applications/mesh/util.c index a19dc71..721cacd 100644 --- a/firmware/applications/mesh/util.c +++ b/firmware/applications/mesh/util.c @@ -37,7 +37,7 @@ void adc_light(void) { while ((getInputRaw())==BTN_NONE){ DoInt(dx,dy,GetLight()); DoInt(dx,dy+16,isNight()); - DoInt(dx,dy+8,globalconfig.backlighttrigger); + DoInt(dx,dy+8,GLOBAL(nighttrigger)); lcdDisplay(); }; dy+=8; diff --git a/firmware/applications/tester/config.c b/firmware/applications/tester/config.c deleted file mode 100644 index 0d8df7c..0000000 --- a/firmware/applications/tester/config.c +++ /dev/null @@ -1,38 +0,0 @@ -#include - -#include "basic/basic.h" - -#include "lcd/print.h" -#include "lcd/display.h" - -#include "filesystem/ff.h" - -#include - -/**************************************************************************/ - -void readcfg(void) { - readConfig(); -}; - -void savecfg(void){ - saveConfig(); -}; - -void applycfg(void){ - applyConfig(); -}; - -void show(void){ - lcdClear(); - lcdPrint("time:"); lcdPrintInt(globalconfig.time); lcdNl(); - lcdPrint("btrig:"); lcdPrintInt(globalconfig.backlighttrigger); lcdNl(); - lcdPrint("bval:"); lcdPrintInt(globalconfig.backlightvalue); lcdNl(); - lcdPrint("lcd:"); lcdPrintInt(globalconfig.lcdstate); lcdNl(); - lcdPrint("priv:"); lcdPrintInt(globalconfig.privacy); lcdNl(); - lcdRefresh(); -}; - -void lcdmirror(void){ - lcdToggleFlag(LCD_MIRRORX); -}; diff --git a/firmware/applications/tester/util.c b/firmware/applications/tester/util.c index 8747264..721cacd 100644 --- a/firmware/applications/tester/util.c +++ b/firmware/applications/tester/util.c @@ -37,13 +37,46 @@ void adc_light(void) { while ((getInputRaw())==BTN_NONE){ DoInt(dx,dy,GetLight()); DoInt(dx,dy+16,isNight()); - DoInt(dx,dy+8,globalconfig.backlighttrigger); + DoInt(dx,dy+8,GLOBAL(nighttrigger)); lcdDisplay(); }; dy+=8; dx=DoString(0,dy,"Done."); }; +void uptime(void) { + int t; + int h; + char flag; + while ((getInputRaw())==BTN_NONE){ + lcdClear(); + lcdPrintln("Uptime:"); + t=getTimer()/(1000/SYSTICKSPEED); + h=t/60/60; + flag=F_ZEROS; + if(h>0){ + lcdPrint(IntToStr(h,2,flag)); + lcdPrint("h"); + flag|=F_LONG; + }; + h=t/60%60; + if(h>0){ + lcdPrint(IntToStr(h,2,flag)); + lcdPrint("m"); + flag|=F_LONG; + }; + h=t%60; + if(h>0){ + lcdPrint(IntToStr(h,2,flag)); + lcdPrint("s"); + }; + lcdNl(); + lcdRefresh(); + delayms_queue(200); + }; + lcdPrintln("done."); +}; + void gotoISP(void) { DoString(0,0,"Enter ISP!"); lcdDisplay();