diff --git a/firmware/applications/final.c b/firmware/applications/final.c new file mode 100644 index 0000000..16525d0 --- /dev/null +++ b/firmware/applications/final.c @@ -0,0 +1,37 @@ +#include + +#include "basic/basic.h" + +#include "lcd/print.h" + +#include + +/**************************************************************************/ + +#include "final.gen" + +static const struct MENU mainmenu = {"Menu", mentry}; + +void initNick(); +void fancyNickname(); + +void main_final(void) { + //checkFirstBoot(); + + initNick(); + while(1){ +#ifndef FINAL + if(getInputRaw()==BTN_LEFT) + ISPandReset(); +#endif + if(getInput()){ + handleMenu(&mainmenu); + getInputWaitRelease(); + initNick(); + }; + fancyNickname(); + delayms_queue(100); + }; +}; + +void tick_final(void); diff --git a/firmware/applications/final/config.c b/firmware/applications/final/config.c new file mode 100644 index 0000000..1451483 --- /dev/null +++ b/firmware/applications/final/config.c @@ -0,0 +1,126 @@ +#include + +#include "basic/basic.h" +#include "basic/config.h" + +#include "lcd/print.h" +#include "lcd/render.h" +#include "lcd/display.h" + +#include "filesystem/ff.h" + +#include + +/**************************************************************************/ + +void readcfg(void) { + readConfig(); +}; + +void savecfg(void){ + saveConfig(); +}; + +void applycfg(void){ + applyConfig(); +}; + +void changer(void){ + uint8_t numentries = 0; + signed char menuselection = 0; + uint8_t visible_lines = 0; + uint8_t current_offset = 0; + + 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/final/flame.c b/firmware/applications/final/flame.c new file mode 100644 index 0000000..a67175c --- /dev/null +++ b/firmware/applications/final/flame.c @@ -0,0 +1,137 @@ +/* + + flame m0dul - https://github.com/kiu/flame + +*/ + +#include "basic/basic.h" +#include "core/i2c/i2c.h" +#include "basic/config.h" + +#define FLAME_I2C_WRITE 0xC4 +#define FLAME_I2C_READ 0xC5 + +#define FLAME_I2C_CR_INPUT 0x00 +#define FLAME_I2C_CR_PSC0 0x01 +#define FLAME_I2C_CR_PWM0 0x02 +#define FLAME_I2C_CR_PSC1 0x03 +#define FLAME_I2C_CR_PWM1 0x04 +#define FLAME_I2C_CR_LS0 0x05 + +#define FLAME_I2C_LS0_OFF 0x00 +#define FLAME_I2C_LS0_ON 0x01 +#define FLAME_I2C_LS0_PWM0 0x02 +#define FLAME_I2C_LS0_PWM1 0x03 + +#define FLAME_I2C_LS0_LED0 0x00 +#define FLAME_I2C_LS0_LED1 0x02 +#define FLAME_I2C_LS0_LED2 0x04 +#define FLAME_I2C_LS0_LED3 0x06 + +#define FLAME_OFF 0x00 +#define FLAME_UP 0x01 +#define FLAME_UP_WAIT 0x02 +#define FLAME_DOWN 0x03 +#define FLAME_DOWN_WAIT 0x04 + +/**************************************************************************/ + +#define flameBrightnessMax GLOBAL(flamemax) +#define flameBrightnessMin GLOBAL(flamemin) +#define flameSpeedUp GLOBAL(flamespeed) +#define flameSpeedDown GLOBAL(flamespeed) +#define flameWaitUp GLOBAL(flamemaxw) +#define flameWaitDown GLOBAL(flameminw) + +uint8_t flameEnabled = 0; +uint8_t flameMode = FLAME_OFF; +uint8_t flameI2Cpwm = 0; +uint8_t flameTicks = 0; + +uint32_t flameSetI2C(uint8_t cr, uint8_t value) { + I2CMasterBuffer[0] = FLAME_I2C_WRITE; + I2CMasterBuffer[1] = cr; + I2CMasterBuffer[2] = value; + I2CWriteLength = 3; + I2CReadLength = 0; + return i2cEngine(); +} + +void setFlamePWM() { + flameSetI2C(FLAME_I2C_CR_PWM0, flameI2Cpwm); // set pwm +} + + +void tick_flame(void) { // every 10ms + flameTicks++; + + if (flameI2Cpwm > flameBrightnessMax) { + flameI2Cpwm = flameBrightnessMax; + } + if (flameI2Cpwm < flameBrightnessMin) { + flameI2Cpwm = flameBrightnessMin; + } + + if (flameMode == FLAME_OFF) { + if (isNight() && flameEnabled) { + flameTicks = 0; + flameMode = FLAME_UP; + } + } + + if (flameMode == FLAME_UP) { + if (flameI2Cpwm + flameSpeedUp > flameI2Cpwm ) { + flameI2Cpwm += flameSpeedUp; + } else { + flameI2Cpwm = 0xFF; + } + push_queue(&setFlamePWM); + if (flameI2Cpwm == flameBrightnessMax) { + flameMode = FLAME_UP_WAIT; + flameTicks = 0; + } + } + + if (flameMode == FLAME_UP_WAIT) { + if (flameTicks >= flameWaitUp) { + flameMode = FLAME_DOWN; + } + } + + if (flameMode == FLAME_DOWN) { + if (flameI2Cpwm - flameSpeedDown < flameI2Cpwm ) { + flameI2Cpwm -= flameSpeedDown; + } else { + flameI2Cpwm = 0x00; + } + push_queue(&setFlamePWM); + if (flameI2Cpwm == flameBrightnessMin) { + flameMode = FLAME_DOWN_WAIT; + flameTicks = 0; + } + } + + if (flameMode == FLAME_DOWN_WAIT) { + if (flameTicks >= flameWaitDown) { + flameMode = FLAME_OFF; + } + } +} + +void flameInit(void) { + + i2cInit(I2CMASTER); // Init I2C + + flameEnabled = (flameSetI2C(FLAME_I2C_CR_LS0, FLAME_I2C_LS0_OFF << FLAME_I2C_LS0_LED0) == I2CSTATE_ACK); // probe i2c + + if (flameEnabled) { + flameSetI2C(FLAME_I2C_CR_LS0, FLAME_I2C_LS0_OFF << FLAME_I2C_LS0_LED0); // set led0 off + flameSetI2C(FLAME_I2C_CR_LS0, FLAME_I2C_LS0_OFF << FLAME_I2C_LS0_LED1); // set led1 off + flameSetI2C(FLAME_I2C_CR_LS0, FLAME_I2C_LS0_OFF << FLAME_I2C_LS0_LED2); // set led2 off + flameSetI2C(FLAME_I2C_CR_LS0, FLAME_I2C_LS0_OFF << FLAME_I2C_LS0_LED3); // set led3 off + + flameSetI2C(FLAME_I2C_CR_PSC0, 0x00); // set prescaler + flameSetI2C(FLAME_I2C_CR_PWM0, 0x00); // set pwm + flameSetI2C(FLAME_I2C_CR_LS0, FLAME_I2C_LS0_PWM0 << FLAME_I2C_LS0_LED0); // set led0 to pwm + } +} diff --git a/firmware/applications/final/mesh.c b/firmware/applications/final/mesh.c new file mode 100644 index 0000000..c6d1f63 --- /dev/null +++ b/firmware/applications/final/mesh.c @@ -0,0 +1,286 @@ +#include +#include +#include + +#include "basic/basic.h" +#include "basic/byteorder.h" + +#include "lcd/lcd.h" +#include "lcd/print.h" + +#include "funk/nrf24l01p.h" + +#include "funk/mesh.h" + +#include + +/**************************************************************************/ + +void m_init(void){ + nrf_init(); + + struct NRF_CFG config = { + .channel= MESH_CHANNEL, + .txmac= MESH_MAC, + .nrmacs=1, + .mac0= MESH_MAC, + .maclen ="\x20", // XXX: MESHPKTSIZE + }; + + nrf_config_set(&config); + + initMesh(); +}; + +void m_tset(void){ + _timet=1311961112; +}; + +void m_time(void){ + struct tm* tm; + char c[2]={0,0}; + getInputWaitRelease(); + delayms(100); + do{ + lcdClear(); + tm= mygmtime(getSeconds()); + lcdPrint(IntToStr(tm->tm_hour,2,F_LONG)); + lcdPrint(":"); + lcdPrint(IntToStr(tm->tm_min,2,F_LONG|F_ZEROS)); + lcdPrint(":"); + lcdPrint(IntToStr(tm->tm_sec,2,F_LONG|F_ZEROS)); + lcdNl(); + lcdPrint(IntToStr(tm->tm_mday,2,F_LONG)); + lcdPrint("."); + lcdPrint(IntToStr(tm->tm_mon+1,2,0)); + lcdPrint("."); + lcdPrint(IntToStr(tm->tm_year+YEAR0,4,F_LONG|F_ZEROS)); + 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)); +}; + + +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/getFontHeight())-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; + + for(int o=0;olo) + if(MO_TYPE(meshbuffer[i].pkt)='a' && tmm[i]<='z'){ + lcdPrintln(IntToStr(MO_TIME(meshbuffer[j].pkt),10,0)); + }else{ + struct tm *tm= mygmtime(MO_TIME(meshbuffer[j].pkt)); + lcdPrint(IntToStr(tm->tm_hour,2,F_LONG)); + lcdPrint(":"); + lcdPrint(IntToStr(tm->tm_min,2,F_LONG|F_ZEROS)); + lcdPrint(":"); + lcdPrint(IntToStr(tm->tm_sec,2,F_LONG|F_ZEROS)); + 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/applications/final/nickname.c b/firmware/applications/final/nickname.c new file mode 100644 index 0000000..9eb46c7 --- /dev/null +++ b/firmware/applications/final/nickname.c @@ -0,0 +1,83 @@ +#include +#include +#include + +#include "basic/basic.h" +#include "basic/byteorder.h" +#include "basic/config.h" + +#include "lcd/lcd.h" +#include "lcd/print.h" + +#include "filesystem/ff.h" +#include "filesystem/select.h" + +#include + +/**************************************************************************/ + +void fancyNickname(void) { + int dx=0; + int dy=0; + static uint32_t ctr=0; + ctr++; + + + lcdClear(); + setExtFont(GLOBAL(nickfont)); + DoString(dx,dy,GLOBAL(nickname)); + lcdRefresh(); + + return; +} + +/**************************************************************************/ + +void initNick(void){ + readFile("nick.cfg",GLOBAL(nickname),MAXNICK); +// readFile("font.cfg",GLOBAL(nickfont),FILENAMELEN); +}; + +void doNick(void){ + input("Nickname:", GLOBAL(nickname), 32, 127, MAXNICK-1); + writeFile("nick.cfg",GLOBAL(nickname),strlen(GLOBAL(nickname))); + getInputWait(); +}; + +void doFont(void){ + getInputWaitRelease(); + if( selectFile(GLOBAL(nickfont),"F0N") != 0){ + lcdPrintln("No file selected."); + return; + }; + + lcdClear(); + lcdPrintln(GLOBAL(nickfont)); + setExtFont(GLOBAL(nickfont)); + lcdPrintln("PUabc€"); + setIntFont(&Font_7x8); + lcdPrintln("done."); + lcdDisplay(); + while(!getInputRaw())delayms(10); +}; + + +#if 0 + void f_font(void){ + + if( selectFile(fontname,"F0N") != 0){ + lcdPrintln("No file selected."); + return; + }; + + lcdClear(); + lcdPrintln(fontname); + setExtFont(fontname); + lcdPrintln("PUabc€"); + setIntFont(&Font_7x8); + lcdPrintln("done."); + lcdDisplay(); + while(!getInputRaw())delayms(10); +}; + +#endif diff --git a/firmware/applications/final/util.c b/firmware/applications/final/util.c new file mode 100644 index 0000000..9876ea4 --- /dev/null +++ b/firmware/applications/final/util.c @@ -0,0 +1,96 @@ +#include +#include + +#include "basic/basic.h" +#include "basic/config.h" + +#include "lcd/print.h" + +#include "usb/usbmsc.h" + +#include "core/iap/iap.h" + +/**************************************************************************/ + +void ChkLight(void) { + int dx=0; + int dy=8; + dx=DoString(0,dy,"Light:"); + DoString(0,dy+16,"Night:"); + while ((getInputRaw())==BTN_NONE){ + DoInt(dx,dy,GetLight()); + DoInt(dx,dy+16,isNight()); + DoInt(dx,dy+8,GLOBAL(daytrig)); + lcdDisplay(); + delayms_queue(100); + }; + dx=DoString(0,dy+24,"Done."); +} + +void ChkBattery(void) { + do{ + lcdClear(); + lcdPrintln("Voltage:"); + lcdPrintln(IntToStr(GetVoltage(),5,0)); + lcdNl(); + lcdPrintln("Chrg_stat:"); + if(gpioGetValue(RB_PWR_CHRG)){ + lcdPrintln("1"); + }else{ + lcdPrintln("0"); + }; + lcdRefresh(); + delayms_queue(100); + } while ((getInputRaw())==BTN_NONE); +} + +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(); + lcdNl(); + lcdPrintln("Ticks:"); + lcdPrint(IntToStr(_timectr,10,0)); + lcdRefresh(); + delayms_queue(200); + }; + lcdPrintln("done."); +} + +void uuid(void) { + IAP_return_t iap_return; + iap_return = iapReadSerialNumber(); + lcdClear(); + lcdPrintln("UUID:"); + lcdPrintIntHex(iap_return.Result[0]); lcdNl(); + lcdPrintIntHex(iap_return.Result[1]); lcdNl(); + lcdPrintIntHex(iap_return.Result[2]); lcdNl(); + lcdPrintIntHex(iap_return.Result[3]); lcdNl(); + lcdNl(); + lcdPrintln("Beacon ID:"); + lcdPrintln(IntToStrX(GetUUID32(),4)); + lcdRefresh(); +} diff --git a/firmware/basic/config.c b/firmware/basic/config.c index 396e500..4393798 100644 --- a/firmware/basic/config.c +++ b/firmware/basic/config.c @@ -11,6 +11,7 @@ struct CDESC the_config[]= { {"version", CFGVER, CFGVER, CFGVER}, + // dflt min max {"privacy", 3, 0, 2 }, {"daytrig", 310/2, 0, 255}, {"daytrighyst", 10, 0, 50 }, @@ -19,6 +20,11 @@ struct CDESC the_config[]= { {"lcdmirror", 0, 0, 1 }, {"lcdinvert", 0, 0, 1 }, {"lcdcontrast", 3, 0, 31 }, + {"flamemax", 255, 0, 255}, + {"flamemin", 0, 0, 255}, + {"flamespeed", 1, 1, 100}, + {"flamemaxw", 255, 1, 255}, + {"flameminw", 0x8f, 1, 255}, { NULL, 0, 0, 0 }, }; diff --git a/firmware/basic/config.h b/firmware/basic/config.h index c4419c5..66365f9 100644 --- a/firmware/basic/config.h +++ b/firmware/basic/config.h @@ -27,6 +27,11 @@ extern char nickfont[]; #define GLOBALlcdmirror (the_config[6].value) #define GLOBALlcdinvert (the_config[7].value) #define GLOBALlcdcontrast (the_config[8].value) +#define GLOBALflamemax (the_config[9].value) +#define GLOBALflamemin (the_config[10].value) +#define GLOBALflamespeed (the_config[11].value) +#define GLOBALflamemaxw (the_config[12].value) +#define GLOBALflameminw (the_config[13].value) #define GLOBALnickname (nickname) #define GLOBALnickfont (nickfont) diff --git a/firmware/basic/menu.c b/firmware/basic/menu.c index 811e356..2216dd2 100644 --- a/firmware/basic/menu.c +++ b/firmware/basic/menu.c @@ -2,7 +2,6 @@ #include "basic/basic.h" -#include "lcd/render.h" #include "lcd/print.h" /**************************************************************************/ @@ -16,11 +15,11 @@ void handleMenu(const struct MENU *the_menu) { if (the_menu == NULL) return; -// font = &Font_7x8; // Font needs to be set externally? + setSystemFont(); for (numentries = 0; the_menu->entries[numentries] != NULL; numentries++); - visible_lines = (RESY/getFontHeight())-1; // subtract title line + visible_lines = lcdGetVisibleLines()-1; // subtract title line #ifdef SAFETY if (visible_lines < 2) return; #endif @@ -75,7 +74,7 @@ void handleMenu(const struct MENU *the_menu) { getInputWaitRelease(); if (the_menu->entries[menuselection]->callback!=NULL) the_menu->entries[menuselection]->callback(); - lcdDisplay(); + lcdRefresh(); getInputWait(); break; diff --git a/firmware/filesystem/select.c b/firmware/filesystem/select.c index 4f755ea..6ca3c47 100644 --- a/firmware/filesystem/select.c +++ b/firmware/filesystem/select.c @@ -69,12 +69,7 @@ int selectFile(char *filename, char *extension) redraw: lcdClear(); - lcdPrint("Select file:"); - lcdSetCrsrX(40); - lcdPrint(IntToStr(skip,1,0)); - lcdPrint("/"); - lcdPrint(IntToStr(selected,1,0)); - lcdNl(); + lcdPrintln("Select file:"); for(int i=0; iSECS_DAY) - meshbuffer[i].flags=MF_FREE; + if (MO_TYPE(meshbuffer[i].pkt)>='a' && + MO_TYPE(meshbuffer[i].pkt)<='z'){ + ; + }else{ + if (MO_TIME(meshbuffer[i].pkt)SECS_DAY) + meshbuffer[i].flags=MF_FREE; + }; }; }; }; @@ -83,37 +106,22 @@ void mesh_recvloop(void){ }; // Safety: Truncate ascii packets by 0-ing the CRC - if (MO_TYPE(buf) >='A' && MO_TYPE(buf) <='Z'){ - buf[MESHPKTSIZE-2]=0; - }; + 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; - }; - }; - }; + // Store packet in a same/free slot + MPKT* mpkt=meshGetMessage(MO_TYPE(buf)); - if(free==-1){ // Buffer full. Ah well. Kill a random packet - free=1; // XXX: GetRandom()? - }; - - if(free<0) + // Skip locked packet + if(mpkt->flags&MF_LOCK) continue; - memcpy(meshbuffer[free].pkt,buf,MESHPKTSIZE); - meshbuffer[free].flags=MF_USED; + // only accept newer/better packets + if(mpkt->flags==MF_USED) + if(MO_TIME(buf)pkt)) + continue; + + memcpy(mpkt->pkt,buf,MESHPKTSIZE); + mpkt->flags=MF_USED; }while(getTimer()MESHBUFSIZE); @@ -137,6 +145,8 @@ void mesh_sendloop(void){ for (int i=0;i #include #include +#include int x=0; int y=0; @@ -69,3 +70,13 @@ void lcdSetCrsr(int dx,int dy){ void lcdSetCrsrX(int dx){ x=dx; }; + +void setSystemFont(void){ + setIntFont(&Font_7x8); +}; + + +int lcdGetVisibleLines(void){ + return (RESY/getFontHeight()); // subtract title line +}; + diff --git a/firmware/lcd/print.h b/firmware/lcd/print.h index d1d8de5..dca2850 100644 --- a/firmware/lcd/print.h +++ b/firmware/lcd/print.h @@ -10,4 +10,5 @@ void lcdRefresh(); void lcdMoveCrsr(signed int dx,signed int dy); void lcdSetCrsr(int dx,int dy); void lcdSetCrsrX(int dx); - +void setSystemFont(void); +int lcdGetVisibleLines(void);