diff --git a/firmware/.gitignore b/firmware/.gitignore index d2d2dd6..5eb99b9 100644 --- a/firmware/.gitignore +++ b/firmware/.gitignore @@ -1,5 +1,6 @@ -firmware.bin -firmware.elf +*.bin +*.elf +*.map lpc1xxx/memory.ld applications/wrapper.c lcd/allfonts.h diff --git a/firmware/Makefile b/firmware/Makefile index 44f6a76..7555ad5 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -37,13 +37,13 @@ ifdef APP OUTFILE=$(APP) endif -LDFLAGS+= -Wl,--gc-sections +LDFLAGS+= --gc-sections OBJS += lpc1xxx/$(TARGET)_handlers.o lpc1xxx/LPC1xxx_startup.o ########################################################################## # Startup files ########################################################################## -LDLIBS = -lm +LDLIBS = LDLIBS += -Lapplications -lapp LDLIBS += -Lfunk -lfunk LDLIBS += -Lusbcdc -lusbcdc @@ -74,7 +74,7 @@ l0dables: table.c @cd l0dable && $(MAKE) clean: - rm -f $(OBJS) $(LD_TEMP) $(OUTFILE).elf $(OUTFILE).bin $(OUTFILE).hex table.c table.h + rm -f $(OBJS) $(LD_TEMP) $(OUTFILE).elf $(OUTFILE).bin $(OUTFILE).hex $(OUTFILE).map table.c table.h for dir in $(SUBDIRS); do \ $(MAKE) $(CONFIG_MAKE_PRINTDIRECTORY) -C $$dir clean; \ done @@ -111,7 +111,7 @@ $(LD_TEMP): -@echo "INCLUDE $(LD_SCRIPT)" >> $(LD_TEMP) $(OUTFILE).elf: $(OBJS) $(SYS_OBJS) $(SUBDIRS) $(LPCFIX) $(LD_TEMP) - $(CC) $(LDFLAGS) -T $(LD_TEMP) -o $(OUTFILE).elf $(OBJS) $(LDLIBS) + $(LD) $(LDFLAGS) -Map=$(OUTFILE).map -T $(LD_TEMP) -o $(OUTFILE).elf $(OBJS) $(LDLIBS) -@echo "" $(SIZE) $(OUTFILE).elf -@echo "" diff --git a/firmware/Makefile.inc b/firmware/Makefile.inc index 3cf227d..dda77a0 100644 --- a/firmware/Makefile.inc +++ b/firmware/Makefile.inc @@ -42,7 +42,7 @@ CPU_TYPE = cortex-$(CORTEX_TYPE) # Compiler settings, parameters and flags ########################################################################## -CFLAGS = -std=c99 -c -g -Os $(INCLUDE_PATHS) -Wall -mthumb -ffunction-sections -fdata-sections -fmessage-length=0 -mcpu=$(CPU_TYPE) -DTARGET=$(TARGET) -DRAMCODE=$(RAMCODE) -fno-builtin -Wno-unused-function +CFLAGS = -std=c99 -c -g -Os $(INCLUDE_PATHS) -Wall -mthumb -ffunction-sections -fdata-sections -fmessage-length=0 -mcpu=$(CPU_TYPE) -DTARGET=$(TARGET) -DRAMCODE=$(RAMCODE) -fno-builtin -Wno-unused-function -ffreestanding LDFLAGS = -nostartfiles ifeq "$(USBSERIAL)" "YES" diff --git a/firmware/README.building b/firmware/README.building index 954edae..6575602 100644 --- a/firmware/README.building +++ b/firmware/README.building @@ -1,4 +1,13 @@ -make flags supported by this Makefile +### A note on the compiler +We are currently using the CodeSourcery gcc (see wiki for link). +You can also use a standard arm cross-gcc + (https://github.com/esden/summon-arm-toolchain) +but please note that this creates larger binaries. +We are talking about 100-200 bytes for firmware.bin, +you will run into space problems with the default firmware. +Sorry about that. + +### Make flags supported by this Makefile APP= - builds "application" foo (check .c and the subdir in applications/) @@ -28,5 +37,5 @@ make APP=l0dable LAPP= (=l0dable.bin) # build all l0dables make l0dables -#build one l0dable +# build one l0dable cd l0dables && make .c0d diff --git a/firmware/applications/final/mesh.c b/firmware/applications/final/mesh.c index 63fb4c1..f2692f0 100644 --- a/firmware/applications/final/mesh.c +++ b/firmware/applications/final/mesh.c @@ -186,6 +186,9 @@ void m_choose(){ case('r'): strcpy(p,"r0type"); break; + case('s'): + strcpy(p,"Snake"); + break; #endif default: p[0]=*mm; @@ -233,6 +236,9 @@ void m_choose(){ case('r'): strcpy(p,"r0type"); break; + case('s'): + strcpy(p,"Snake"); + break; #endif }; if(tmm[i]>='a' && tmm[i]<='z'){ diff --git a/firmware/basic/basic.c b/firmware/basic/basic.c index 51c1950..5b908df 100644 --- a/firmware/basic/basic.c +++ b/firmware/basic/basic.c @@ -18,7 +18,7 @@ void rbInit() { gpioSetDir(USB_CONNECT, gpioDirection_Output); gpioSetValue(USB_CONNECT, 1); - uint8_t ports[] = { RB_BTN0, RB_BTN1, RB_BTN2, RB_BTN3, RB_BTN4, + static uint8_t ports[] = { RB_BTN0, RB_BTN1, RB_BTN2, RB_BTN3, RB_BTN4, RB_LED0, RB_LED1, RB_LED2, RB_SPI_SS0, RB_SPI_SS1, RB_SPI_SS2, RB_SPI_SS3, RB_SPI_SS4, RB_SPI_SS5, diff --git a/firmware/basic/basic.h b/firmware/basic/basic.h index 4025232..694e778 100644 --- a/firmware/basic/basic.h +++ b/firmware/basic/basic.h @@ -171,12 +171,12 @@ uint16_t crc16(uint8_t * buf, int len); // menu.c struct MENU_DEF { - char *text; + const char *text; void (*callback)(void); }; struct MENU { - char *title; + const char *title; struct MENU_DEF entries[]; }; diff --git a/firmware/basic/ecc.h b/firmware/basic/ecc.h index 05b1d3b..a99c173 100644 --- a/firmware/basic/ecc.h +++ b/firmware/basic/ecc.h @@ -1,5 +1,6 @@ #ifndef _ECC_H_ #define _ECC_H_H +#include #include /******************************************************************************/ diff --git a/firmware/core/libc/stdio.c b/firmware/core/libc/stdio.c old mode 100755 new mode 100644 diff --git a/firmware/core/libc/string.c b/firmware/core/libc/string.c old mode 100755 new mode 100644 index 3fe0b9c..e6bb0fe --- a/firmware/core/libc/string.c +++ b/firmware/core/libc/string.c @@ -52,6 +52,7 @@ void * memcpy(void *pDestination, const void *pSource, size_t num) { unsigned char *pByteDestination; unsigned char *pByteSource; +#ifdef FAST_MEMCPY unsigned int *pAlignedSource = (unsigned int *) pSource; unsigned int *pAlignedDestination = (unsigned int *) pDestination; @@ -71,6 +72,10 @@ void * memcpy(void *pDestination, const void *pSource, size_t num) // Copy remaining bytes pByteDestination = (unsigned char *) pAlignedDestination; pByteSource = (unsigned char *) pAlignedSource; +#else + pByteDestination = (unsigned char *) pDestination; + pByteSource = (unsigned char *) pSource; +#endif while (num--) { *pByteDestination++ = *pByteSource++; diff --git a/firmware/core/sysdefs.h b/firmware/core/sysdefs.h index bf79c8e..018c147 100644 --- a/firmware/core/sysdefs.h +++ b/firmware/core/sysdefs.h @@ -39,20 +39,12 @@ #ifndef _SYSDEFS_H_ #define _SYSDEFS_H_ +#include "../sysdefs.h" + #include #include #include -// Stay compatible with ugly "windows" style -#define BOOL bool -#define TRUE true -#define FALSE false - -typedef volatile uint8_t REG8; -typedef volatile uint16_t REG16; -typedef volatile uint32_t REG32; -typedef unsigned char byte_t; - #define pREG8 (REG8 *) #define pREG16 (REG16 *) #define pREG32 (REG32 *) diff --git a/firmware/filesystem/select.c b/firmware/filesystem/select.c index 07399f1..d9b2f45 100644 --- a/firmware/filesystem/select.c +++ b/firmware/filesystem/select.c @@ -8,6 +8,7 @@ #define FLEN 13 +/* if count is 0xff (-1) do not fill files and return the count instead */ int getFiles(char files[][FLEN], uint8_t count, uint16_t skip, const char *ext) { DIR dir; /* Directory object */ @@ -37,7 +38,9 @@ int getFiles(char files[][FLEN], uint8_t count, uint16_t skip, const char *ext) continue; }; - strcpy(files[pos++],Finfo.fname); + if(count != 0xff) + strcpy(files[pos],Finfo.fname); + pos++; if( pos == count ) break; } @@ -50,17 +53,19 @@ int selectFile(char *filename, const char *extension) int skip = 0; char key; int selected = 0; + int file_count = getFiles(NULL, 0xff, 0, extension); + font=&Font_7x8; + if(!file_count){ + lcdPrintln("No Files?"); + lcdRefresh(); + getInputWait(); + getInputWaitRelease(); + return -1; + }; while(1){ char files[PERPAGE][FLEN]; int count = getFiles(files, PERPAGE, skip, extension); - if(!count){ - lcdPrintln("No Files?"); - lcdRefresh(); - getInputWait(); - getInputWaitRelease(); - return -1; - }; if(count 0 ){ skip--; + } else { // wrap to bottom + skip = file_count - PERPAGE; + if(skip < 0) skip = 0; + selected = file_count - skip - 1; } } break; case BTN_LEFT: + getInputWaitRelease(); return -1; case BTN_ENTER: case BTN_RIGHT: strcpy(filename, files[selected]); + getInputWaitRelease(); return 0; } } diff --git a/firmware/funk/mesh.c b/firmware/funk/mesh.c index e75603e..96a4965 100644 --- a/firmware/funk/mesh.c +++ b/firmware/funk/mesh.c @@ -13,6 +13,10 @@ char meshgen=0; // Generation char meshincctr=0; char meshmsg=0; char meshnice=0; + +char mesh_mode=0; +#define MM_TIME (1<<0) +#define MM_ENC (1<<1) MPKT meshbuffer[MESHBUFSIZE]; #include "SECRETS" @@ -23,6 +27,8 @@ static int mesh_gt(char curgen, char newgen){ unsigned char dif=curgen-newgen; if(curgen==0) return 1; + if(newgen==0) + return 0; return (dif>128); }; @@ -43,21 +49,24 @@ void initMesh(void){ int mesh_sanity(uint8_t * pkt){ if(MO_TYPE(pkt)>0x7f || MO_TYPE(pkt)<0x20) return MP_SEND; + if(MO_TYPE(pkt)=='T' && MO_BODY(pkt)[5]) + return MP_SEND; if(MO_TYPE(pkt)=='T' && MO_TIME(pkt)<86400) return MP_OK; if(MO_TYPE(pkt)>='A' && MO_TYPE(pkt)<='Z'){ - if(MO_TIME(pkt)>1326409200) + if(MO_TIME(pkt)>1370340000) /* 4.Jun 2013 */ return MP_SEND; - if(MO_TIME(pkt)<1324602000) + if(MO_TIME(pkt)<1325376000) /* 1.1.2012 */ return MP_SEND; }else if(MO_TYPE(pkt)>='a' && MO_TYPE(pkt)<='z'){ - if(MO_TIME(pkt)>16777216) + if(MO_TIME(pkt)>16777216) /* 3-byte only */ return MP_SEND; if(MO_TIME(pkt)<0) return MP_SEND; }; if(MO_TYPE(pkt)!='A' && MO_TYPE(pkt)!='a' && + MO_TYPE(pkt)!='i' && MO_TYPE(pkt)!='B' && MO_TYPE(pkt)!='E' && MO_TYPE(pkt)!='F' && @@ -97,6 +106,7 @@ void meshPanic(uint8_t * pkt,int bufno){ #if 0 static int done=0; if(!done){ + gpioSetValue (RB_LED0, 1-gpioGetValue(RB_LED0)); setSystemFont(); lcdClear(); lcdPrint("PANIC["); @@ -105,9 +115,15 @@ void meshPanic(uint8_t * pkt,int bufno){ lcdNl(); for(int i=0;i<32;i++){ lcdPrint(IntToStrX(pkt[i],2)); - if(i%6==5) + if(i%6==2){ + lcdPrint(" "); + }; + if(i%6==5){ lcdNl(); + }; } + lcdPrint(" "); + lcdPrint(IntToStrX(crc16(pkt,30),4)); lcdRefresh(); while ((getInputRaw())==BTN_NONE); }; @@ -156,10 +172,13 @@ void mesh_sendloop(void){ // Update [T]ime packet MO_TIME_set(meshbuffer[0].pkt,getSeconds()); MO_GEN_set(meshbuffer[0].pkt,meshgen); - if(GLOBAL(privacy)==0) + if(GLOBAL(privacy)==0){ uint32touint8p(GetUUID32(),meshbuffer[0].pkt+26); - else + uint32touint8p(getrelease(),meshbuffer[0].pkt+22); + }else{ uint32touint8p(0,meshbuffer[0].pkt+26); + uint32touint8p(0,meshbuffer[0].pkt+22); + }; MO_BODY(meshbuffer[0].pkt)[4]=meshnice; @@ -223,7 +242,7 @@ uint8_t mesh_recvqloop_work(void){ if(mesh_sanity(buf)){ meshincctr++; if((mesh_sanity(buf)&MP_RECV)!=0){ - meshPanic(buf,-1); + meshPanic(buf,-len); }; return 0; }; @@ -235,6 +254,7 @@ uint8_t mesh_recvqloop_work(void){ meshincctr=0; meshnice=MO_BODY(buf)[4]; meshgen=MO_GEN(buf); + mesh_mode&=~MM_TIME; }; }; @@ -243,15 +263,19 @@ uint8_t mesh_recvqloop_work(void){ return 0; }; - // Set new time iff newer - if(MO_TYPE(buf)=='T'){ - time_t toff=MO_TIME(buf)-((getTimer()+(600/SYSTICKSPEED))/(1000/SYSTICKSPEED)); - if (toff>_timet){ // Do not live in the past. - _timet = toff; - meshincctr++; - }; - return 1; - }; + // Set new time iff I don't have a valid one. + if((mesh_mode & MM_TIME)==0){ + if(MO_TYPE(buf)=='T'){ + time_t toff=MO_TIME(buf)-((getTimer()+(600/SYSTICKSPEED))/(1000/SYSTICKSPEED)); + _timet = toff; + if(meshgen==0 && MO_TIME(buf)<60*60*24){ + ; // still not valid + }else{ + mesh_mode|=MM_TIME; // Got a time now. + }; + return 1; + }; + }; // Safety: Truncate ascii packets by 0-ing the CRC buf[MESHPKTSIZE-2]=0; @@ -318,7 +342,7 @@ void mesh_recvqloop_end(void){ nrf_config_set(&oldconfig); } -void mesh_recvloop(void){ +void mesh_recvloop(void){ /* unused: replaced by mesh_recvloop_plus */ int recvend=M_RECVTIM/SYSTICKSPEED+getTimer(); int pktctr=0; @@ -329,7 +353,7 @@ void mesh_recvloop(void){ }else{ delayms_power(10); }; - }while(getTimer()MESHBUFSIZE); + }while(getTimer()tm_sec,2,F_LONG|F_ZEROS)); lcdNl(); + lcdPrint(" "); lcdPrint(IntToStr(tm->tm_mday,2,F_LONG)); lcdPrint("."); lcdPrint(IntToStr(tm->tm_mon+1,2,0)); @@ -132,6 +134,11 @@ void m_time(void){ lcdNl(); lcdPrint("Inc:"); lcdPrintInt(meshincctr); + + lcdPrint(" SP:"); + __asm( "mov %0, sp\n" : "=r" (sp) :); + lcdPrint(IntToStrX(sp,4)); + lcdNl(); lcdPrint("Nice:"); lcdPrintInt(meshnice); @@ -168,6 +175,8 @@ void m_time(void){ case BTN_UP: active=1; break; + case BTN_NONE: + break; default: return; }; diff --git a/firmware/l0dable/help/memcpy.c b/firmware/l0dable/help/memcpy.c new file mode 100644 index 0000000..42e900d --- /dev/null +++ b/firmware/l0dable/help/memcpy.c @@ -0,0 +1,10 @@ +#include +#include "../usetable.h" + +#undef memcpy + +void * memcpy(void *dst, const void *src, size_t len){ + return + (*(void * (*)(void *, const void *, size_t ))(*(TheTable+_memcpy_nr))) + (dst, src, len); +}; diff --git a/firmware/l0dable/jeopardy.c b/firmware/l0dable/jeopardy.c index c3b31d1..35b0c4c 100644 --- a/firmware/l0dable/jeopardy.c +++ b/firmware/l0dable/jeopardy.c @@ -90,6 +90,8 @@ void setLeft(); void setRight(); struct packet a; +void setJeopardy(); + void ram(void) { int priv = GLOBAL(privacy); @@ -103,7 +105,7 @@ void ram(void) nrf_config_set(&config); nrf_set_strength(3); - int rnd; +// int rnd; volatile uint16_t i; while( 1 ){ diff --git a/firmware/l0dable/jump.c b/firmware/l0dable/jump.c index a83d940..e1add11 100644 --- a/firmware/l0dable/jump.c +++ b/firmware/l0dable/jump.c @@ -221,7 +221,7 @@ static void draw_platforms() { } static void draw_player() { - bool* sprite; + const bool* sprite; if(game.player_y_vel > 0) { sprite = PLAYER_SPRITE_DOWN; } diff --git a/firmware/l0dable/mktable.pl b/firmware/l0dable/mktable.pl index cceebe7..f55b9ee 100755 --- a/firmware/l0dable/mktable.pl +++ b/firmware/l0dable/mktable.pl @@ -5,6 +5,7 @@ use strict; my $DIR="l0dable"; +my $memcpy; if( -d "../$DIR"){ chdir(".."); @@ -105,10 +106,16 @@ for my $idx (0..$#symb){ print C "$_,"; }; print I "#define $_ ($types{$_}(TheTable[$idx]))"; + if($_ eq "memcpy" || $_ eq "memmove"){ + $memcpy=$idx + }; }; print C "};"; +if (defined($memcpy)){ + print I "#define _memcpy_nr $memcpy"; +}; close(I); close(H); close(C); diff --git a/firmware/l0dable/nick_work.c b/firmware/l0dable/nick_work.c index 2875c3d..519fa4a 100644 --- a/firmware/l0dable/nick_work.c +++ b/firmware/l0dable/nick_work.c @@ -71,11 +71,12 @@ int melody_timeout; static void init_lilakit(void); static void tick_lilakit(void); +void melody_play(void); static void mainloop(); void handler(void); void ram(void) { - timer32Callback0 = handler; + timer32Callback0 = (uint32_t) handler; /* Enable the clock for CT32B0 */ SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT32B0); diff --git a/firmware/l0dable/people.c b/firmware/l0dable/people.c index 4f85e17..28118f6 100644 --- a/firmware/l0dable/people.c +++ b/firmware/l0dable/people.c @@ -29,7 +29,7 @@ void ram(void) { if( nrf_rcv_pkt_time(64,sizeof(buf),buf) == 16 ){ buf[14] = 0; if( buf[1] == 0x23 || buf[1] == 0x24){ - lcdPrintln(buf+6); + lcdPrintln((char*)(buf+6)); //lcdPrintln("foo"); } lcdRefresh(); diff --git a/firmware/l0dable/pongo.c b/firmware/l0dable/pongo.c index 150ea22..891c05f 100644 --- a/firmware/l0dable/pongo.c +++ b/firmware/l0dable/pongo.c @@ -113,6 +113,9 @@ void init(); ** Code Section *********************************************/ +void init(); +void ram(); + void game(void) { init(); @@ -139,7 +142,7 @@ void game(void) } } -init() +void init() { // init ball ball1.size = PONG_BALL_SIZE; diff --git a/firmware/l0dable/r_player.c b/firmware/l0dable/r_player.c index c2602df..da538ca 100644 --- a/firmware/l0dable/r_player.c +++ b/firmware/l0dable/r_player.c @@ -34,11 +34,11 @@ struct packet{ uint8_t x; uint8_t y; uint8_t flags; - uint8_t text[16]; + char text[16]; }__attribute__((packed)) text; struct nick{ uint8_t flags; - uint8_t nick[18]; + char nick[18]; }__attribute__((packed)) nick; struct nickrequest{ uint8_t reserved[19]; @@ -55,7 +55,7 @@ struct packet{ uint8_t gameFlags; uint8_t interval; uint8_t jitter; - uint8_t gameTitle[8]; + char gameTitle[8]; }__attribute__((packed)) announce; struct join{ uint16_t gameId; @@ -93,7 +93,7 @@ uint16_t gameId; uint8_t interval; uint8_t jitter; uint8_t flags; -uint8_t *gameTitle; +char *gameTitle; void sendButton(uint8_t button); void sendJoin(uint32_t game); @@ -321,7 +321,7 @@ void processNickRequest( struct nickrequest *nq) p.id= id; p.ctr= ++ctr; p.c.nick.flags = 0; - uint8_t *nick = GLOBAL(nickname); + char *nick = GLOBAL(nickname); strcpy(p.c.nick.nick, nick); nrf_snd_pkt_crc(sizeof(p),(uint8_t*)&p); } @@ -374,7 +374,7 @@ void processText(struct text *t) if( t->flags & FLAGS_CLS ) lcdClear() ; lcdSetCrsr(t->x, t->y); - t->text[16] = 0; + t->text[16] = 0; // XXX:Actually ok, beause the CRC is there. But evil! lcdPrint(t->text); lcdRefresh(); } diff --git a/firmware/l0dable/scope.c b/firmware/l0dable/scope.c index 6b44ecb..7603be6 100644 --- a/firmware/l0dable/scope.c +++ b/firmware/l0dable/scope.c @@ -116,7 +116,7 @@ void ram(void) { case BTN_RIGHT: if (kok) { xs++; xs&=63; kok=0; } break; case BTN_UP: if (kok) { ch++; ch&=7; kok=0; } break; case BTN_DOWN: if (kok) { ch--; ch&=7; kok=0; } break; - case BTN_ENTER: return 0; + case BTN_ENTER: return; default: kok=1; } } diff --git a/firmware/l0dable/snake.c b/firmware/l0dable/snake.c new file mode 100644 index 0000000..ce7a56c --- /dev/null +++ b/firmware/l0dable/snake.c @@ -0,0 +1,322 @@ +/* + * snake + ******** + * a snake clone for the r0ket + * created by Flori4n (DrivenHoliday) & MascH (CCCHB tent) + ***************************************/ + +#include +#include + +#include "basic/basic.h" +#include "basic/config.h" +#include "basic/random.h" +#include "lcd/render.h" +#include "lcd/display.h" +#include "lcd/fonts.h" +#include "lcd/fonts/invaders.h" +//#Include "lcd/lcd.h" +//#include "lcd/print.h" +#include "funk/mesh.h" +#include "usetable.h" + +#define MAX_SNAKE_LEN (40) +#define SNAKE_DIM (3) +#define MIN_SPEED (25) +#define MAX_SPEED (3) +#define MIN_X 2 +#define MAX_X (RESX-3) +#define MIN_Y 8 +#define MAX_Y (RESY-2) +#define SIZE_X ((MAX_X-MIN_X)/SNAKE_DIM) +#define SIZE_Y ((MAX_Y-MIN_Y)/SNAKE_DIM) + +#define RIGHT 0 +#define LEFT 2 +#define UP 3 +#define DOWN 1 + +struct pos_s { + int x,y; +}; + +struct snake_s { + struct pos_s *tail; + int len, dir, speed, t_start; +}; + +static void reset(); +static void next_level(); +static void draw_block(); +static void handle_input(); +static void death_anim(); +static struct pos_s getFood(void); +static int hitWall(); +static int hitFood(); +static int hitSelf(); +static int showHighscore(); + +int points = 0; +struct snake_s snake = { NULL, 3, 0, MIN_SPEED, 2}; +struct pos_s food; + +void ram(void) +{ + int c=0, pos=0,del=0; + + struct pos_s tail[MAX_SNAKE_LEN]; + snake.tail = tail; + + // initially reset everything + reset(); + + while (1) + { + if(!(++c % snake.speed)) { + handle_input(); + + pos = (snake.t_start+1) % MAX_SNAKE_LEN; + snake.tail[pos].x = snake.tail[snake.t_start].x; + snake.tail[pos].y = snake.tail[snake.t_start].y; + + if(snake.dir == 0) + snake.tail[pos].x++; + else if(snake.dir == 1) + snake.tail[pos].y++; + else if(snake.dir == 2) + snake.tail[pos].x--; + else if(snake.dir == 3) + snake.tail[pos].y--; + + snake.t_start = pos; + + if (pos < snake.len) { + del = MAX_SNAKE_LEN - (snake.len - pos); + } else + del = pos - snake.len; + + // remove last, add first line + draw_block(snake.tail[del].x, snake.tail[del].y, 0); + draw_block(snake.tail[pos].x, snake.tail[pos].y, 1); + + // check for obstacle hit.. + if (hitWall() || hitSelf()) { + death_anim(); + if (showHighscore()) + break; + reset(); + } + else if (hitFood()) + next_level(); + + lcdDisplay(); + } + +#ifdef SIMULATOR + delayms(50); +#else + delayms(3); +#endif + } +} + +static struct pos_s getFood(void) +{ + int i,pos; + struct pos_s res; + + tryagain: + res.x = (getRandom() % (SIZE_X-1)) + 1; + res.y = (getRandom() % (SIZE_Y-3)) + 3; + + for(i=0; i= MAX_X) + || (snake.tail[snake.t_start].y*3 <= MIN_Y) + || (snake.tail[snake.t_start].y*3 >= MAX_Y) ) ? + 1 : 0; + +} + +static int hitSelf() +{ + int i, pos; + for (i=1; ipkt)>score) + return false; + + MO_TIME_set(mpkt->pkt,score); + strcpy((char*)MO_BODY(mpkt->pkt),nick); + if(GLOBAL(privacy)==0){ + uint32touint8p(GetUUID32(),mpkt->pkt+26); + mpkt->pkt[25]=0; + }; + return true; +} + +static uint32_t highscore_get(char nick[]){ + MPKT * mpkt= meshGetMessage('s'); + char * packet_nick = (char*)MO_BODY(mpkt->pkt); + // the packet crc end is already zeroed + if(MAXNICKpkt); +} + +static int showHighscore() +{ + int key = getInputRaw(); //throw away pending keypress + char nick[20]; + uint32_t score = 0; + + highscore_set(points,GLOBAL(nickname)); + score = highscore_get(nick); + + lcdClear(); + DoString(0,RESY/2-33, " Your Score"); + DoInt(RESX/2-4, RESY/2-25, points); + DoString(0,RESY/2-10, " Highscore"); + DoInt(RESX/2-4, RESY/2-2, score); + DoString(0, RESY/2+18, " UP to play "); + DoString(0, RESY/2+26, "DOWN to quit "); + + lcdDisplay(); + + while(1) { + key = getInputRaw(); + if (key&BTN_DOWN) { + return 1; + } else if (key&BTN_UP) { + return 0; + } + } +} + +static int hitFood() +{ + return ((snake.tail[snake.t_start].x == food.x) && (snake.tail[snake.t_start].y == food.y)) ? 1 : 0; +} diff --git a/firmware/l0dable/snake.c.disabled b/firmware/l0dable/snake.c.disabled deleted file mode 100644 index 9422712..0000000 --- a/firmware/l0dable/snake.c.disabled +++ /dev/null @@ -1,194 +0,0 @@ -#include -#include "basic/basic.h" -#include "basic/config.h" - -#include "lcd/lcd.h" -#include "lcd/print.h" -#include "usetable.h" - -struct elem -{ - int x,y; -}; - -void reset(struct elem snake[],size_t *snake_size,int *dirc, -int*speed, int*points,int*point_s); -void o_rectangle (int x0, int y0, int width, int height); -struct elem rnd(void); - -#define MAX_SNAKE_LEN (40) -#define SNAKE_DEM (3) -#define MIN_SPEED (25) -#define MAX_SPEED (3) -#define SIZE_X (RESX) -#define SIZE_Y (RESY) - -void ram(void) -{ - int inpt,dirc,c,grows = 0,dx,dy,points,point_s=1; - size_t n = 0, snake_size = 5, speed=MIN_SPEED; - struct elem snake[MAX_SNAKE_LEN], food; - char test[512]; /* scratch space */ - o_init (test, sizeof(test)); - - reset(snake,&snake_size,&dirc,&speed,&points,&point_s); - - food = rnd(); - - while (1) - { - head: - if(!(++c % speed)) - { - - -inpt = getInputRaw(); - -dx=DoString(0,0,IntToStrX(points,2)); - dx=(SIZE_X-dx)/2; - if(dx<0) - dx=0; - dy=(SIZE_Y-getFontHeight())/2; - - lcdFill(255); - o_rectangle(1,0,SIZE_X-2,SIZE_Y-2); - o_set_gray (0); - o_fill (); - - //o_identity (); /* reset tranforms */ - - o_set_gray (50); - - setExtFont("UBUNTU29"); - - lcdSetPixel(1,1,1); - DoString(dx,dy,IntToStrX(points,2)); - - o_set_gray (255); - - - for(n=0;n SIZE_Y/SNAKE_DEM-1 || -t.x > SIZE_X/SNAKE_DEM) - { - reset(snake,&snake_size,&dirc,&speed,&points,&point_s); - goto head; - } - - for(n=0;n MAX_SPEED) --speed; - food = rnd(); - } - } - - if(!grows) - { - for(n=0;n=3550 && old_state != 2){ + drawCommonThings(c); lcdPrintln(" Charge soon"); - }else if (mv<4000){ + rectFill(16, 25, 12, 16, true); + old_state = 2; + }else if (c && mv<4000 && mv>=3650 && old_state != 3){ + drawCommonThings(c); lcdPrintln(" OK"); - }else if(mv<4200){ + rectFill(16, 25, 12, 16, true); + rectFill(30, 25, 12, 16, true); + old_state = 3; + }else if (c && mv<4120 && mv>=4000 && old_state != 4){ + drawCommonThings(c); lcdPrintln(" Good"); - }else{ + rectFill(16, 25, 12, 16, true); + rectFill(30, 25, 12, 16, true); + rectFill(44, 25, 12, 16, true); + old_state = 4; + }else if (c && mv>=4120 && old_state != 5){ + drawCommonThings(c); lcdPrintln(" Full"); - }; + rectFill(16, 25, 12, 16, true); + rectFill(30, 25, 12, 16, true); + rectFill(44, 25, 12, 16, true); + rectFill(58, 25, 12, 16, true); + old_state = 5; + } - lcdNl(); - lcdPrint(" "); + // Print voltage. (Every frame). + lcdSetCrsr(0, 50); + v = mv/1000; + lcdPrint(" "); lcdPrint(IntToStr(v,2,0)); lcdPrint("."); - lcdPrint(IntToStr(mv%1000,3,F_ZEROS)); + lcdPrint(IntToStr(mv%1000, 3, F_ZEROS | F_LONG)); lcdPrintln("V"); - - lcdNl(); - if(c){ - lcdPrintln("(not charging)"); - }; + lcdSetCrsr(0, 0); lcdRefresh(); } while ((getInputWaitTimeout(242))==BTN_NONE); } + +void drawCommonThings(int c) { + lcdClear(); + // Print header. + lcdPrintln("Battery status:"); + + // Draw battery frame. + hLine(23, 14, 72, true); + hLine(43, 14, 72, true); + vLine(14, 23, 43, true); + vLine(72, 23, 28, true); + vLine(72, 38, 43, true); + hLine(28, 72, 78, true); + hLine(38, 72, 78, true); + vLine(78, 28, 38, true); + + // Print if not charging. + lcdSetCrsr(0, 60); + if(c){ + lcdPrintln("(not charging)"); + }; + lcdSetCrsr(0, 10); +} + +void hLine(int y, int x1, int x2, bool pixel) { + for (int i=x1; i<=x2; ++i) { + lcdSetPixel(i, y, pixel); + } +} + +void vLine(int x, int y1, int y2, bool pixel) { + for (int i=y1; i<=y2; ++i) { + lcdSetPixel(x, i, pixel); + } +} + +void rectFill(int x, int y, int width, int heigth, bool pixel) { + for (int i=y; i<=y+heigth; ++i) { + hLine(i, x, x+width, pixel); + } +} diff --git a/firmware/lcd/display.c b/firmware/lcd/display.c index 2e60e08..b9efaf1 100644 --- a/firmware/lcd/display.c +++ b/firmware/lcd/display.c @@ -166,7 +166,16 @@ void lcdInit(void) { lcd_select(); if(displayType==DISPLAY_N1200){ - uint8_t initseq[]= { 0xE2,0xAF, // Display ON + /* Decoded: + * E2: Internal reset + * AF: Display on/off: DON = 1 + * A1: undefined? + * A4: all on/normal: DAL = 0 + * 2F: charge pump on/off: PC = 1 + * B0: set y address: Y[0-3] = 0 + * 10: set x address (upper bits): X[6-4] = 0 + */ + static uint8_t initseq[]= { 0xE2,0xAF, // Display ON 0xA1, // Mirror-X 0xA4, 0x2F, 0xB0, 0x10}; int i = 0; @@ -175,7 +184,29 @@ void lcdInit(void) { delayms(5); // actually only needed after the first } }else{ /* displayType==DISPLAY_N1600 */ - uint8_t initseq_d[] = { + static uint8_t initseq_d[] = { + /* Decoded: + * CMD 36: MADCTL (argument missing!) + * CMD 29: DISPON + * CMD BA: Data order (1) + * DAT 07: ignored? + * CMD 15: undefined? + * DAT 25: ignored? + * DAT 3F: ignored? + * CMD 11: sleep out + * CMD 13: normal display mode on + * CMD 37: set scroll entry point + * DAT 00: scroll entry point + * CMD 3A: interface pixel format + * DAT 05: 16 bit/pixel + * CMD 2A: column address set + * DAT 0 : xs + * DAT 98-1 : xe + * CMD 2B: page address set + * DAT 0 : ys + * DAT 70-1 : ye + */ + 0x36, 0x29, 0xBA, 0x07, 0x15, 0x25, 0x3f, @@ -239,9 +270,12 @@ static void _helper_hline(uint16_t color){ _helper_pixel16(color); } -#define THECOLOR_R 0x0 -#define THECOLOR_G 0x60 -#define THECOLOR_B 0x0 +#define COLORPACK_RGB565(r,g,b) (((r&0xF8) << 8) | ((g&0xFC)<<3) | ((b&0xF8) >> 3)) + +static const uint16_t COLOR_FG = COLORPACK_RGB565(0x00, 0x60, 0x00); +static const uint16_t COLOR_BG = COLORPACK_RGB565(0xff, 0xff, 0xff); +static const uint16_t COLOR_FRAME = COLORPACK_RGB565(0x00, 0x00, 0x80); + void lcdDisplay(void) { char byte; @@ -266,25 +300,17 @@ void lcdDisplay(void) { } } } else { /* displayType==DISPLAY_N1600 */ - unsigned char r=THECOLOR_R,g=THECOLOR_G,b=THECOLOR_B; - unsigned char br=0xFF, bg=0xFF, bb=0xFF; - unsigned char frame_r=0x00, frame_g=0x00, frame_b=0x80; - uint16_t color,framecolor,backcolor; uint16_t x,y; bool px; - uint16_t actualcolor; - color = ((r&0xF8) << 8) | ((g&0xFC)<<3) | ((b&0xF8) >> 3); - framecolor= ((frame_r&0xF8) << 8) | ((frame_g&0xFC)<<3) | ((frame_b&0xF8) >> 3); - backcolor= ((br&0xF8) << 8) | ((bg&0xFC)<<3) | ((bb&0xF8) >> 3); lcdWrite(TYPE_CMD,0x2C); //top line of the frame... - _helper_hline(framecolor); + _helper_hline(COLOR_FRAME); for(y=RESY;y>0;y--){ //left line of the frame - _helper_pixel16(framecolor); + _helper_pixel16(COLOR_FRAME); for(x=RESX;x>0;x--){ if(GLOBAL(lcdmirror)) @@ -292,17 +318,19 @@ void lcdDisplay(void) { else px=lcdGetPixel(x-1,y-1); - if((!px)^(!GLOBAL(lcdinvert))) actualcolor=color; - else actualcolor=backcolor; /* white */ + if((!px)^(!GLOBAL(lcdinvert))) { + _helper_pixel16(COLOR_FG); /* foreground */ + } else { + _helper_pixel16(COLOR_BG); /* background */ + } - _helper_pixel16(actualcolor); } //right line of the frame - _helper_pixel16(framecolor); + _helper_pixel16(COLOR_FRAME); } //bottom line of the frame - _helper_hline(framecolor); + _helper_hline(COLOR_FRAME); } lcd_deselect(); } diff --git a/firmware/main.c b/firmware/main.c index 3a66d2e..67c740f 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -4,7 +4,10 @@ #include "core/pmu/pmu.h" #include "basic/basic.h" +#include "basic/config.h" #include "lcd/render.h" +#include "lcd/print.h" +#include "usb/usbmsc.h" #include "filesystem/ff.h" @@ -34,7 +37,7 @@ void wrapper(void); -int main(void) { +void main(void) { // Configure cpu and mandatory peripherals cpuInit(); // Configure the CPU // we do it later @@ -77,5 +80,5 @@ int main(void) { } int getrelease(void){ - return 0x00000108; + return 0x0000010d; }; diff --git a/firmware/release-all b/firmware/release-all index 0ba0d5b..bc0853c 100755 --- a/firmware/release-all +++ b/firmware/release-all @@ -1,5 +1,11 @@ #!/bin/sh -e +# We currently don't use crypto, so this script is deprecated. + +if [ -z ${MAKE} ]; then + which gmake >/dev/null && MAKE=gmake || MAKE=make +fi + TARG=../release if [ ! -d ../firmware ] ; then @@ -32,9 +38,9 @@ echo "###" echo "### Building final" echo "###" export FINAL=y -make clean +$MAKE clean ./l0dable/mktable.pl -make APP=final +$MAKE APP=final cp firmware.elf $TARG/final.elf cp firmware.bin $TARG/final.bin @@ -48,7 +54,7 @@ cp ../tools/image/lcd/i42.lcd $TARG/files/nick.lcd echo "###" echo "### Gathering loadables" echo "###" -(cd l0dable && make) +(cd l0dable && $MAKE) mv l0dable/*.c0d $TARG/files/ mv l0dable/*.int $TARG/files/ mv l0dable/*.nik $TARG/files/ @@ -59,7 +65,7 @@ if grep -q 'define ENCRYPT_L0DABLE' SECRETS ; then echo "###" echo "### Building crypto" echo "###" -(cd ../tools/crypto && make) +(cd ../tools/crypto && $MAKE) echo "###" echo "### Crypting loadables" diff --git a/firmware/sysdefs.h b/firmware/sysdefs.h index 10ebfb4..d17cb54 100644 --- a/firmware/sysdefs.h +++ b/firmware/sysdefs.h @@ -36,10 +36,10 @@ */ /**************************************************************************/ -#ifndef _SYSDEFS_H_ -#define _SYSDEFS_H_ +#ifndef _GLOBAL_SYSDEFS_H_ +#define _GLOBAL_SYSDEFS_H_ -#include +#include #include #include @@ -53,18 +53,9 @@ typedef volatile uint16_t REG16; typedef volatile uint32_t REG32; typedef unsigned char byte_t; -#define pREG8 (REG8 *) -#define pREG16 (REG16 *) -#define pREG32 (REG32 *) - -#ifndef NULL -#define NULL ((void *) 0) -#endif - // Save some space #ifndef SIMULATOR #define memcpy memmove #endif #endif - diff --git a/tools/mesh/beacontrace.pl b/tools/mesh/beacontrace.pl new file mode 100755 index 0000000..fe90f61 --- /dev/null +++ b/tools/mesh/beacontrace.pl @@ -0,0 +1,118 @@ +#!/usr/bin/perl +# +# vim:set ts=4 sw=4: + +use strict; +use Curses; +use POSIX qw(strftime); +use Time::HiRes qw(time); + +use lib '.'; +use r0ket; + +$|=1; + +r0ket::r0ket_init(); + +# Default openbeacon settings. +r0ket::set_txmac(pack("H*","0102030201")); +r0ket::set_rxmac(pack("H*","0102030201")); +r0ket::set_channel(81); +r0ket::set_rxlen(16); + +#r0ket::readbeacon(); + +my $str; +my %bdata; + +sub do_str; + +initscr; +END{endwin;} +use constant WIDTH => 80; +use constant m_height => 15; +my $win_top=subwin(2,WIDTH,0,0); +my $win=subwin(m_height,WIDTH,2,0); +noecho; +curs_set(0); +$win_top->addstr(0,0,"r0ket Beacon-Trace 0.1"); +$win_top->addstr(1,0,"-"x20); +$win_top->refresh; + +my $beaconctr=0; +use constant CLEAN => 10; +use constant UPDATE => 0.3; +my $lasttime; +my $lastcleantime; +my $clean; +my $crcerr=0; +while(1){ + $str=r0ket::get_packet(); + my $p=r0ket::nice_beacon($str); + if($p->{crc} ne "ok"){ + $crcerr++; + next; + }; + + if($p->{type} eq "beacon"){ + $bdata{$p->{beacon}}{seen}=time; + $bdata{$p->{beacon}}{beacon}=$p; + $bdata{$p->{beacon}}{stats}{$p->{strength}}++; + if(!defined($bdata{$p->{beacon}}{stats}{first})){ + $bdata{$p->{beacon}}{stats}{first}=time; + }; + }elsif($p->{type} eq "nick"){ + $bdata{$p->{beacon}}{nick}=$p->{nick}; + }else{ #unknown + ; + }; + + if(time>$lastcleantime+CLEAN){ + $clean=1; + $lastcleantime=time; + }else{ + $clean=0; + }; + + my $line=0; + if($clean){ + $win->clear; + for my $b (sort keys %bdata){ + if($bdata{$b}{seen}+10$lasttime+UPDATE){ + for my $b (sort keys %bdata){ + $win->addstr($line++,0, + sprintf "%s | bt=%s idx=%8s | %s | %s", + $b, + $bdata{$b}{beacon}->{button}, + $bdata{$b}{beacon}->{idx}, + do_str($bdata{$b}{stats}), + $bdata{$b}{nick}." " + ); + }; + $win_top->addstr(1,20,sprintf" cnt=%2d, crc=%d",scalar(keys %bdata),$crcerr); + $win_top->refresh; + + $win->refresh; + $lasttime=time; + }; +}; +r0ket::rest(); + +sub do_str{ + my $hr=shift; + my $df=time()-$hr->{first}; + $df=1 if $df==0; + my $out=""; +# for(sort keys %$hr){ + for(qw(00 55 aa ff)){ + next if $_ eq "first"; + $out.=sprintf("%3d% ",($hr->{$_}/$df)*100/2); + }; + + return $out; +}; diff --git a/tools/mesh/dbg.pl b/tools/mesh/dbg.pl index 667591b..887cd38 100755 --- a/tools/mesh/dbg.pl +++ b/tools/mesh/dbg.pl @@ -137,8 +137,9 @@ if($cmd =~ /^r/){ print "t="; # print unpack("N",substr($str,2,4))," "; print strftime("%Y-%m-%d %H:%M:%S",gmtime unpack("N",substr($str,2,4))); - printf " (%+3d) ",unpack("N",substr($str,2,4))-(time+3600); - print "beacon=",resolvebeacon(unpack("H*",substr($str,26,4)))," "; + printf " (%+3d)",unpack("N",substr($str,2,4))-(time+3600); + print " rel=",unpack("H*",substr($str,24,2)); + print " beacon=",resolvebeacon(unpack("H*",substr($str,26,4)))," "; }elsif($i eq "i"){ print "score=",unpack("N",substr($str,2,4))," "; print "nick=",unpack("Z*",substr($str,6,length($str)-8))," "; diff --git a/tools/mesh/meshtrace.pl b/tools/mesh/meshtrace.pl new file mode 100755 index 0000000..2788083 --- /dev/null +++ b/tools/mesh/meshtrace.pl @@ -0,0 +1,63 @@ +#!/usr/bin/perl +# +# vim:set ts=4 sw=4: + +use strict; +use Curses; +use POSIX qw(strftime); + +use lib '.'; +use r0ket; + +$|=1; + +r0ket::r0ket_init(); + +# Default mesh settings. +r0ket::set_txmac("ORBIT"); +r0ket::set_rxmac("ORBIT"); +r0ket::set_channel(83); +r0ket::set_rxlen(32); + +r0ket::readbeacon(); + +my $str; +my %bdata; + +initscr; +END{endwin;} +use constant WIDTH => 80; +use constant m_height => 15; +my $win_top=subwin(2,WIDTH,0,0); +my $win=subwin(m_height,WIDTH,2,0); +noecho; +curs_set(0); +$win_top->addstr(0,0,"r0ket Mesh-Trace 0.1"); +$win_top->addstr(1,0,"-"x20); +$win_top->refresh; + +my $beaconctr=0; +my $crcerr=0; +while(1){ + $str=r0ket::get_packet(); + my $p=r0ket::nice_mesh($str); + if($p->{crc} ne "ok"){ + $crcerr++; + next; + }; + + if(!$bdata{$p->{beacon}}){ + $bdata{$p->{beacon}}=++$beaconctr; + }; + $win->addstr($bdata{$p->{beacon}},0, + sprintf "%s | g=%d rel=%s time=%s =%+4d | %s", + $p->{beacon}, + $p->{generation}, + $p->{release}, + strftime("%Y-%m-%d %H:%M:%S",gmtime $p->{time}), + $p->{time}-(time+3600), + r0ket::getbeacon($p->{beacon}) + ); + $win->refresh; +}; +r0ket::rest(); diff --git a/tools/mesh/r0ket.pm b/tools/mesh/r0ket.pm new file mode 100755 index 0000000..38baaab --- /dev/null +++ b/tools/mesh/r0ket.pm @@ -0,0 +1,345 @@ +#!/usr/bin/perl +# +# vim:set ts=4 sw=4: + +use strict; + +use IO::Select; +package r0ket; + +use Digest::CRC qw(crcccitt); +use POSIX qw(strftime); +use Time::HiRes; + +our $verbose=0; +our $bridge; # Open device + +### Utility +sub sprint{ + return join("",map { + if (ord($_)>30 && ord($_)<127){ + $_; + }else{ +# "[x".unpack("H*",$_)."]"; + "\\".unpack("C",$_); + } + }split(//,shift)); +}; + +sub hprint{ + return unpack("H*",shift); +}; + +sub flagsstr { + my $in=shift; + my @f; + my $f=1; + for (@_){ + if($in & $f){ + push @f,$_; + }; + $f*=2; + }; + return join(",",@f); +}; + + + + +### Nickname/beacon helper functions +our %beacon; +sub readbeacon{ + return if( ! -f "BEACON" ); + open(B,"<","BEACON") || die "open: $!"; + while(){ + /(\w+)\s+(.*)/ && do { + $beacon{$1}=$2; + }; + }; + close(B); +}; +sub getbeacon{ + my $b=shift; + if(!$beacon{$b}){ + return ""; + }else{ + return $beacon{$b}; + }; +}; +sub resolvebeacon{ + my $b=shift; + if(!$beacon{$b}){ + return $b; + }else{ + return "$b ($beacon{$b})"; + }; +}; +sub addbeacon{ + my($b,$n)=@_; + if(!$beacon{$b}){ + $beacon{$b}=$n; + }; +}; +sub writebeacon{ + open(B,">","BEACON") || die "write: $!"; + for(sort keys %beacon){ + print B "$_ $beacon{$_}\n"; + }; + close(B); +}; + +### Packet mgmt + +our $buffer; +our $firstpkt=2; +sub get_packet{ + sub _get_bytes{ + my $rr; + sysread($bridge,$rr,1024); + if(length($rr)<=1){ + select(undef,undef,undef,0.05); + }; + $buffer.=$rr; + }; + + my $cnt=0; + while(++$cnt<100){ + if(length($buffer)<2){ + _get_bytes(); + }elsif($buffer !~ /^\\[12]/){ + $buffer=~s/^(.[^\\]*)//s; + if($firstpkt){ + $firstpkt--; + }else{ + print STDERR "Unparseable stuff: <",sprint($1),">\n"; + }; + }elsif ($buffer =~ s/^\\2\\0//s){ + return 'ack'; # In-band signalling. Evil %) + }elsif ($buffer =~ s/^\\1(.*?)\\0//s){ + my $str=$1; + $str=~s/\\\\/\\/g; # dequote + return $str; + }else{ + _get_bytes(); + }; + }; + die "No packets for 5seconds?\n"; +}; + +sub rest{ + if(length($buffer)>0){ + print "rest: <", sprint($buffer), ">\n"; + }; +}; + +### Pkt beautify +sub nice_mesh{ + my $pkt=shift; + my $out; + my $type=substr($pkt,0,1); +# next if(defined $arg && $arg ne $i); + $out->{type}=$type; + $out->{string}="[$type]"; + $out->{generation}=unpack("C",substr($pkt,1,1)); + $out->{string}.= " g=".$out->{generation}; + if($type eq "T"){ + $out->{time}= unpack("N",substr($pkt,2,4)); + $out->{release}=unpack("H*",substr($pkt,24,2)); + $out->{beacon}= unpack("H*",substr($pkt,26,4)); + + $out->{string}.=sprintf " t=%s (%+4d) rel=%s beacon=%s", + strftime("%Y-%m-%d %H:%M:%S",gmtime $out->{time}), + $out->{time}-(Time::HiRes::time+3600), + $out->{release}, + resolvebeacon($out->{beacon}); + }elsif($type eq "i"){ + $out->{score}=unpack("N",substr($pkt,2,4)); + $out->{nick}= unpack("Z*",substr($pkt,6,length($pkt)-8)); + + $out->{string}.=sprintf " score=%d nick=%s", + $out->{score}, + $out->{nick}; + }elsif($type eq "B"){ + $out->{time}=unpack("N",substr($pkt,2,4)); + $out->{id}= unpack("c",substr($pkt,6,1)); + $out->{hop}= unpack("n",substr($pkt,11,4)); + + $out->{string}.=sprintf " t=%d id=%s hop=%3d", + $out->{time}, + $out->{id}, + $out->{hop}; + }else{ + $out->{string}.= " "; + }; + + my $pkt_crc= unpack("n",substr($pkt,length($pkt)-2,2)); + my $calc_crc= crcccitt(substr($pkt,0,length($pkt)-2)); + + if ($pkt_crc eq $calc_crc){ + $out->{crc}="ok"; + }else{ + $out->{crc}="fail"; + $out->{string}.= " CRCFAIL"; + }; + + return $out; +}; + +sub nice_game{ + my $pkt=shift; + my $out; + my $type=substr($pkt,2,1); + + $out->{proto}=substr($pkt,1,1); + $out->{type} =substr($pkt,2,1); + $out->{id} =unpack("V",substr($pkt,3,4)); + $out->{ctr} =unpack("V",substr($pkt,7,4)); + + $out->{string}=sprintf "G[%s] id=%d ctr=%d", + $out->{type}, $out->{id}, $out->{ctr}; + + if($type eq "A"){ + $out->{mac} = substr($pkt,11,5); + $out->{channel} = unpack("C" ,substr($pkt,16,1)); + $out->{id} = unpack("v", substr($pkt,17,2)); + $out->{flags} = unpack("C", substr($pkt,19,1)); + $out->{flagsstr}=flagsstr($out->{flags},qw(mass short lrecv)); + $out->{interval} = unpack("C", substr($pkt,20,1)); + $out->{jitter} = unpack("C", substr($pkt,21,1)); + $out->{title} = unpack("Z*",substr($pkt,22,10)); + + $out->{string}.=sprintf " mac=%s ch=%s id=%d fl=<%s> itvl=%d j=%d %s", + sprint($out->{mac}), + $out->{channel}, + $out->{id}, + $out->{flagsstr}, + $out->{interval}, + $out->{jitter}, + $out->{title}; + }else{ + $out->{string}.= " "; + }; + + my $pkt_crc= unpack("n",substr($pkt,length($pkt)-2,2)); + my $calc_crc= crcccitt(substr($pkt,0,length($pkt)-2)); + + if ($pkt_crc eq $calc_crc){ + $out->{crc}="ok"; + }else{ + $out->{crc}="fail"; + $out->{string}.= " CRCFAIL"; + }; + + return $out; +}; + +sub nice_beacon{ + my $pkt=shift; + my $out; + my $type=substr($pkt,1,1); + $out->{type}=$type; + + if($type eq "\x17"){ + $out->{type}= "beacon"; + $out->{length}= unpack("C", substr($pkt,0,1)); + $out->{button}= unpack("H*",substr($pkt,2,1)); + $out->{strength}=unpack("H*",substr($pkt,3,1)); + $out->{idx}= unpack("N", substr($pkt,4,4)); + $out->{beacon}= unpack("H*",substr($pkt,8,4)); + $out->{unused}= unpack("H*",substr($pkt,12,2)); + + $out->{string}=sprintf "BEACON ln=%d bt=%s str=%s idx=%08x beacon=%s", + $out->{length}, + $out->{button}, + $out->{strength}, + $out->{idx}, + $out->{beacon}; + if(unpack("H*",substr($pkt,12,2)) ne "ffff"){ + print "unused=",unpack("H*",substr($pkt,12,2))," "; + }; + }elsif($type eq "\x23"){ + $out->{type}= "nick"; + $out->{beacon}= unpack("H*",substr($pkt,2,4)); + $out->{nick}= unpack("Z*",substr($pkt,6,length($pkt)-2)); + + $out->{string}=sprintf "NICK beacon=%s nick=%s", + $out->{beacon}, + $out->{nick}; + }else{ + $out->{string}=""; + }; + + my $pkt_crc= unpack("n",substr($pkt,length($pkt)-2,2)); + my $calc_crc= crcccitt(substr($pkt,0,length($pkt)-2)); + + if ($pkt_crc eq $calc_crc){ + $out->{crc}="ok"; + }else{ + $out->{crc}="fail"; + $out->{string}.= " CRCFAIL"; + }; + + return $out; +}; + +sub r0ket_init{ + my $ser; + if ($ARGV[0] eq "-s"){ + shift; + $ser=shift; + }; + if(!defined $ser){ + if (defined $ENV{R0KETBRIDGE} && -e $ENV{R0KETBRIDGE}){ + $ser=$ENV{R0KETBRIDGE} + }; + }; + if(!defined $ser){ + do {$ser=$_ if ( -e $_ ) } for qw(/dev/ttyS3 /dev/ttyACM0); + }; + open($bridge, "+<",$ser) || die "open serial: $!"; + if($verbose){ + print "using: $ser\n"; + }; +}; + +sub send_raw { + if($verbose){ + print "send: ",unpack("H*",$_[0]),"\n"; + }; + syswrite($bridge,shift); +}; + +sub send_pkt_num { + my $pkt=shift; + $pkt=~s/\\/\\\\/; + send_raw('\\'.shift().$pkt.'\0'); +}; + +sub send_pkt { + send_pkt_num(shift,1); +}; + +sub set_txmac { + send_pkt_num(shift,3); +}; +sub set_rxmac { + send_pkt_num(shift,4); +}; +sub set_channel { + send_pkt_num(pack("C",shift),5); +}; +sub set_rxlen { + send_pkt_num(pack("C",shift),6); +}; + +sub wait_ok { + my $pkt; + $pkt=get_packet(); + while($pkt ne "ack"){ + print "pkt=",(sprint $pkt),"\n"; + $pkt=get_packet(); + }; + print "ok!\n"; + return 1; +}; +1; diff --git a/tools/mesh/rf b/tools/mesh/rf new file mode 100755 index 0000000..5bf5b17 --- /dev/null +++ b/tools/mesh/rf @@ -0,0 +1,266 @@ +#!/usr/bin/perl +# +# vim:set ts=4 sw=4: + +use strict; + +use IO::Select; +use Digest::CRC qw(crcccitt); +use POSIX qw(strftime); + +use FindBin; +use lib "$FindBin::Bin"; +use r0ket; + +$|=1; + +r0ket::r0ket_init(); + +my @fh; +my $read; + +if ($ARGV[0] =~ /^-?-?h/){ + print STDERR "Mini-Help:\n"; + print STDERR "-s (or \$R0KETBRIDGE)\n"; + print STDERR "-w write beacon2nick file\n"; + print STDERR "\n"; + print STDERR "recv: receive (number) pakets\n"; + print STDERR " - r hex : hexdump packets\n"; + print STDERR " - r ascii : asciidump packets\n"; + print STDERR " - r beacon : parse as openbeacon\n"; + print STDERR " - r mesh : parse as mesh packet\n"; + print STDERR " - r game : parse as game packet(incomplete)\n"; + print STDERR "\n"; + print STDERR "send: send packet (number) times\n"; + print STDERR " - s raw : send raw hex packet\n"; + print STDERR " - s hex : send packet with crc16\n"; + print STDERR " - s mesh t : send mesh time packet\n"; + print STDERR " - s mesh , see source :-)\n"; + print STDERR "\n"; + print STDERR "preset: config per preset\n"; + print STDERR "- p m - preset minimesh\n"; + print STDERR "- p b - preset openbeacon\n"; + print STDERR "- p a - preset game announce\n"; + print STDERR "- p r - preset sample game\n"; + print STDERR "config: config rf chip\n"; + print STDERR "- c rx - set rxmac\n"; + print STDERR "- c tx - set txmac\n"; + print STDERR "- c len - set rxlength\n"; + print STDERR "- c ch - set channel\n"; + print STDERR "- c hex - set any option via hex string\n"; + print STDERR "\n"; + print STDERR "etc...\n"; + exit(1); +}; + +my $writend=0; +if ($ARGV[0] eq "-w"){ + shift; + $writend=1; +}; + +END{ + r0ket::writebeacon if($writend); +}; + +my $cmd=shift; + +if($cmd =~ /^r/){ + r0ket::readbeacon(); + $cmd=~s/r(ecv)?//; + $cmd=100 if $cmd+0==0; + my $fmt=shift || "_"; + my $arg=shift || undef; + my $read=""; + + my $str; + while($cmd>0){ + $str=r0ket::get_packet(); + + if($fmt =~ /_/){ + if(substr($str,0,1)eq "\x10"){ + if(substr($str,1,1)eq"G"){ + $fmt="g_"; + }else{ + $fmt="b_"; + }; + }elsif(substr($str,0,1)eq "\x20"){ + $fmt="g_"; + }elsif(length($str)==32){ + $fmt="m_"; + }else{ + $fmt="x_"; + }; + }; + + if($fmt =~ /^m/){ + my $p=r0ket::nice_mesh($str); + print $p->{string}; + }elsif($fmt =~ /^b/){ + my $p=r0ket::nice_beacon($str); + print $p->{string}; + }elsif($fmt =~ /^g/){ + my $p=r0ket::nice_game($str); + print $p->{string}; + }elsif($fmt =~ /^(x|hex)/){ + my $pkt_crc= unpack("n",substr($str,length($str)-2,2)); + my $calc_crc= crcccitt(substr($str,0,length($str)-2)); + print "<",unpack("H*",$str),">"; + if($pkt_crc ne $calc_crc){ + print " CRCFAIL"; + }; + }elsif($fmt =~ /^a/){ + print "<", r0ket::sprint($str), ">"; + }else{ + die "Unknown packet format: $fmt\n"; + }; + print "\n"; + $cmd--; + next; + }; + r0ket::rest(); +}elsif ($cmd =~ /^p/){ # Preset + my $sub=shift; + if ($sub =~/^m/i){ # Default mesh settings. + r0ket::set_txmac("ORBIT"); + r0ket::set_rxmac("ORBIT"); + r0ket::set_channel(83); + r0ket::set_rxlen(32); + }elsif ($sub =~/^b/i){ # Default OpenBeacon settings + r0ket::set_txmac(pack("H*","0102030201")); + r0ket::set_rxmac(pack("H*","0102030201")); + r0ket::set_channel(81); + r0ket::set_rxlen(16); + }elsif ($sub =~/^a/i){ # Default rem0te announce settings + r0ket::set_txmac("REM0T"); + r0ket::set_rxmac("REM0T"); + r0ket::set_channel(87); + r0ket::set_rxlen(32); + }elsif ($sub =~/^r/i){ # Default bpong game settings + r0ket::set_txmac("BPONG"); + r0ket::set_rxmac("BPONG"); + r0ket::set_channel(91); + r0ket::set_rxlen(32); + }else{ + die "Unkown preset $sub\n"; + }; +}elsif ($cmd =~ /^c/){ + my $set=shift; + + if($set=~s/hex//){ + $ARGV[0]=pack("H*",$ARGV[0]); + }; + if ($set =~ /^tx/){ + r0ket::set_txmac(shift); + }elsif ($set =~ /^rx/){ + r0ket::set_rxmac(shift); + }elsif ($set =~ /^ch/){ + r0ket::set_channel(shift); + }elsif ($set =~ /^len/){ + r0ket::set_rxlen(shift); + }else{ + die "Unknown config argument $set\n"; + }; + r0ket::wait_ok(); + +}elsif ($cmd =~ /^s/){ + $cmd=~s/^//; + $cmd=1 if $cmd==0; + + my $pkt; + + my $sub=shift; + if($sub =~ /^raw/){ + $pkt=pack("H*",shift); + }elsif($sub =~ /^hex/){ + $pkt=pack("H*",shift); + $pkt.=pack("n",crcccitt($pkt)); + }elsif($sub =~ /^m/){ + my $scmd=shift; + + if($scmd eq "t"){ + $pkt.="T"; + $pkt.=chr(shift); #gen + $pkt.=pack("N",scalar(time)+1*60*60); + + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + }elsif($scmd eq "a"){ + $pkt.="A"; + $pkt.=chr(shift); #gen + $pkt.=pack("N",scalar(time)+1*60*60+ 300); + + $pkt.= pack("C",shift||0); + $pkt.= pack("C",0); + $pkt.= pack("C",0); + $pkt.= pack("C",0); + + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + }elsif($scmd eq "b"){ + $pkt.="B"; + $pkt.=chr(shift); #gen + $pkt.=pack("N",scalar(time)+1*60*60+ 600); + + $pkt.= pack("C",shift||0); + $pkt.= pack("C",0); + $pkt.= pack("C",0); + $pkt.= pack("C",0); + + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + }elsif($scmd eq "c"){ + $pkt.="\x1"; + $pkt.=chr(shift); #gen + $pkt.=pack("N",scalar(time)+1*60*60+ 600); + + $pkt.= pack("C",shift||0); + $pkt.= pack("C",0); + $pkt.= pack("C",0); + $pkt.= pack("C",0); + + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + $pkt.=pack("N",0); + }elsif($scmd eq "i"){ + $pkt.="i"; + $pkt.=chr(shift); #gen + $pkt.=pack("N",shift||42); + + $pkt.=shift; + $pkt.="\0"x(30-length($pkt)); + }else{ + die "Unknown mesh subtype: $scmd\n"; + }; + $pkt.=pack("n",crcccitt($pkt)); + }else{ + die "Unknown send subtype: $sub\n"; + }; + + print "Write: <", r0ket::sprint($pkt),">, "; + print "crc: ",unpack("n",substr($pkt,length($pkt)-2,2))," "; + print "len: ",length($pkt),"\n"; + while($cmd-->0){ + r0ket::send_pkt($pkt); + r0ket::wait_ok; + }; +}else{ + die "Option not understood\n"; +}; + +#if (@fh = $sel->can_read(10)) { +# sysread($fh[0],$read,1024); +#} +#print "PostRead: <", sprint($read), ">\n"; diff --git a/tools/smartflash/.gitignore b/tools/smartflash/.gitignore new file mode 100644 index 0000000..b211c62 --- /dev/null +++ b/tools/smartflash/.gitignore @@ -0,0 +1,2 @@ +firmware.bin +files diff --git a/tools/smartflash/Makefile b/tools/smartflash/Makefile index b9770df..acd9615 100644 --- a/tools/smartflash/Makefile +++ b/tools/smartflash/Makefile @@ -1,7 +1,20 @@ +default: build setup + +all: build setup run + +redo: rebuild setup run + +build: cleanbuild rebuild + +cleanbuild: + cd ../../firmware && make clean + +rebuild: + cd ../../firmware && make && make l0dables + setup: - cd ../../firmware && make clean && make && make l0dables cp ../../firmware/firmware.bin . - -mkdir files + mkdir -p files cp ../../firmware/l0dable/*c0d files cp ../../firmware/l0dable/*nik files cp ../../firmware/l0dable/*int files @@ -12,10 +25,11 @@ setup: cd ../crypto && make clean && make generate-keys cp ../crypto/generate-keys . @echo - @echo Now run ./smartflash + @echo "Now run ./smartflash (as root)" + +run: + sudo ./smartflash clean: rm -f firmware.bin generate-keys rm -rf files - -