diff --git a/minuteur/bitmaps.h b/minuteur/bitmaps.h index 2d13677..c28a45d 100644 --- a/minuteur/bitmaps.h +++ b/minuteur/bitmaps.h @@ -63,6 +63,9 @@ const char * _finish_= const char * _logo_ = "Star Trek:o=5,d=16,b=63,b=63:8f.,a#,4d#6.,8d6,a#.,g.,c6.,4f6"; const char * _neon_ = "Neonligh:d=4,o=5,b=100:8e#7,16p,16d#7,8d#7,8p,16c#7,8c#6,16a#6,8e#7,16p,16d#7,8d#7,8p,8c#7,16a#6,8e#7,16p,16a#6,8a#6,8p,16c#7,8d#7,16e#7,8e#7,16p,8d#7"; +const char * _com_ = "Communic:d=4,o=5,b=100:16g#7,8a#7,16a#7,16a#7,8f#7"; +const char * _pop_ = "Popcorn:d=1,o=5,b=800:8c6,8a#,8c6,8g,8d#,8g,c6"; +const char * _clk_ = "clock:d=16,o=8,b=420:b7,32p,c"; void playRTTTL (screen_t itune){ //#ifdef SOUND_ON @@ -71,32 +74,42 @@ void playRTTTL (screen_t itune){ return; case sLOGO : anyrtttl::blocking::play(PIEZO, _logo_); break; case sTITRE : ; break; //rtune = _missip1_ - case sCHOIX : anyrtttl::blocking::play(PIEZO, _neon_); break; + case sCHOIX : anyrtttl::blocking::play(PIEZO, _com_); break; case sEXPOS : anyrtttl::blocking::play(PIEZO, _finish_); break; case sREGLE : ; break; //tune = _count_ default : ; break; } } +void playPop(){ anyrtttl::blocking::play(PIEZO, _pop_);} +void playClk(){ anyrtttl::blocking::play(PIEZO, _clk_);} + +// Snooze screen saver +#define SNOOZE_HEIGHT 16 +#define SNOOZE_WIDTH 16 +#define XPOS 0 // Indexes into the 'icons' array in function below +#define YPOS 1 +#define DELTAY 2 +#define _DISPLAYWIDTH 128 +#define _DISPLAYHEIGHT 32 +#define FLOCONS 4 // snowflakes in animation + +const unsigned char flake_bmp [] PROGMEM = { + 0x01, 0x80, 0xc3, 0xc3, 0xe3, 0xc7, 0xfb, 0xdf, 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, 0x0f, 0xf0, + 0x0f, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0xfb, 0xdf, 0xe3, 0xc7, 0xc3, 0xc3, 0x01, 0x80 +}; +// 'smiley', 16x16px +const unsigned char smiley_bmp [] PROGMEM = { + 0x07, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x7f, 0xfc, 0x63, 0x8c, 0xdd, 0x76, 0xd3, 0x96, 0xe7, 0xce, + 0xff, 0xfe, 0xfd, 0x7e, 0x6f, 0xec, 0x73, 0x9c, 0x3c, 0x78, 0x1f, 0xf0, 0x07, 0xc0, 0x00, 0x00 +}; +// 'frown', 16x16px +const unsigned char frown_bmp [] PROGMEM = { +0x07, 0xc0, 0x1f, 0xf0, 0x3f, 0xf8, 0x67, 0xcc, 0x53, 0x94, 0xdd, 0x76, 0xd9, 0x36, 0xe1, 0x0e, + 0xff, 0xfe, 0xff, 0xfe, 0x78, 0x3c, 0x73, 0x9c, 0x37, 0xd8, 0x1f, 0xf0, 0x07, 0xc0, 0x00, 0x00 +}; +//sprite_t smiley = { 6, 16, 16, 0, 1, 2, smiley_bmp }; +//sprite_t frown = { unsigned short c6, 16, 16, 0, 1, 2, frown_bmp }; + -/* -// flower -static const unsigned char PROGMEM flower_bmp[] = { - 0b00000000, 0b11000000, - 0b00000001, 0b11000000, - 0b00000001, 0b11000000, - 0b00000011, 0b11100000, - 0b11110011, 0b11100000, - 0b11111110, 0b11111000, - 0b01111110, 0b11111111, - 0b00110011, 0b10011111, - 0b00011111, 0b11111100, - 0b00001101, 0b01110000, - 0b00011011, 0b10100000, - 0b00111111, 0b11100000, - 0b00111111, 0b11110000, - 0b01111100, 0b11110000, - 0b01110000, 0b01110000, - 0b00000000, 0b00110000 }; -*/ #endif // _INSOLAB_BITMAP_H_ diff --git a/minuteur/concepdoc/etats_InsoLab.dot b/minuteur/concepdoc/etats_InsoLab.dot index 9e822aa..dcf3af6 100755 --- a/minuteur/concepdoc/etats_InsoLab.dot +++ b/minuteur/concepdoc/etats_InsoLab.dot @@ -10,17 +10,17 @@ digraph InsoLab { graph [ rankdir=TB, // Top Bottom, BT,LR,Rl overlap=false, splines=true, sep="+0.5", - ranksep=1.4, // in top down mode => Vert distance between nodes - nodesep=1.4, // in top down mode => horz distance between nodes + ranksep=1.8, // in top down mode => Vert distance between nodes + nodesep=1.6, // in top down mode => horz distance between nodes fontname="Arial", fontsize=50, style=filled, fillcolor="#FFC0A0", color = "#FFC0A0" ]; - size="7,6"; // h,l + size="7,8"; // h,l pad=1; // margins / clusters label="\nDiagramme d'enchaînement des écrans."; subgraph cluster_ecrans { - fontsize=60; + fontsize=70; style=filled; fillcolor="#FFFFFF"; label="Le minuteur de l'InsoL@b\n"; color = "#FFFFFF";//"#FFC0A0";//"#FFFFFF"; @@ -29,49 +29,57 @@ subgraph cluster_ecrans { node [ shape=box,style="filled,setlinewidth(2)",fontsize=30, afixedsize=true, height=2.5, width=3.8 ]; edge [style="filled,setlinewidth(8)" fontsize=30 arrowsize=2 ] - CHOIX [label="CHOIX\nBoutton avec:\n- exposer UV\n+ régler durées", + CHOIX [label="CHOIX\nBouton avec:\n- exposer UV\n+ régler durées", fillcolor="#FFA550"]; - EXPOS [label="EXPOS\nDécompte de\nla durée avec\nexposition UV", + EXPOS [label="EXPOS\nDécompte durée UV\n- abandon\n+ ajout incrément", fillcolor="#FFC0CB:#FF69B4", style=radial]; REGLE [label="REGLE\nRéglages avec:\n- changer le pas\n+ changer la durée", fillcolor="#FFF080"] ; + SAUVE [label="SAUVE\n- non quitter\n+ oui sauver en\nFlash & quitter", fillcolor="#ffcec4"]; node [ shape=box,style="filled,setlinewidth(2)",fontsize=30, afixedsize=true, height=1.8, width=3.8 ]; - LOGO [label="LOGO\nÉcran d'accueil\naffiché 4s", fillcolor="#FFFFFF"]; - TITRE [label="TITRE\nAttente appui\nd'un boutton", fillcolor="#7CFC60"]; + LOGO [label="LOGO\nAccueil & lecture\nréglages en Flash", fillcolor="#FFFFFF"]; + TITRE [label="TITRE\nAttente appui\nd'un bouton", fillcolor="#7CFC60"]; DUREE [label="DUREE\nChange la\ndurée sous UV", fillcolor="#FF98FF"] ; INCRE [label="INCRE\nChange le pas\nréglant la durée", fillcolor="aqua"]; { rank = same LOGO TITRE INCRE } - { rank = same EXPOS CHOIX REGLE } //node [group = "R"] //REGLE; DUREE; INCRE; + { rank = same EXPOS CHOIX REGLE SAUVE} //node [group = "R"] //REGLE; DUREE; INCRE; node [shape=box, afixedsize=true, height=.7, width=3.8]; Réveil ; Veille;//[shape=box, afixedsize=true, height=.8, width=3.8]; /* ================================ Arcs ================================*/ VCC:s -> LOGO:n [ taillabel ="Mise\nsous\ntension " ]; - Réveil:s -> TITRE:n [ taillabel= "\nSortie \nde veille ",label=" Bouton +" ]; + Réveil:s -> TITRE:n [ taillabel= "\nSortie \nde veille ",label=" Bouton + ou -", + taillabel= "\nSortie \nde veille "]; LOGO:e -> TITRE:w [ taillabel =" Fin délai\n" ]; TITRE:e -> INCRE:w [ style=invis]; - TITRE:s -> CHOIX:n [ taillabel ="\nBoutton + " ] ; - CHOIX:w -> EXPOS:e [ taillabel ="\nBoutton - " ]; - CHOIX:e -> REGLE:w [ taillabel =" Boutton +" ] ; + TITRE:s -> CHOIX:n [ taillabel ="\nBouton + ou - " ] ; + + CHOIX:nw -> EXPOS:ne [ label ="Bouton -" ]; + CHOIX:ne -> REGLE:nw [ label ="Bouton +" ] ; CHOIX:s -> Veille:n [ - taillabel= "\nMise en veille au\ndélai d'activité expiré " ]; - EXPOS:n -> CHOIX:nw [ taillabel ="Fin du\ndécompte\n" ]; + headlabel= "\nDélai\nsans activité \n expiré " ]; + EXPOS:se -> CHOIX:sw [ headlabel ="Fin\ndécompte \n\n" ]; EXPOS:n -> LOGO:s [ style=invis]; REGLE:n -> INCRE:s [ taillabel=" - \n\n" ]; - REGLE:s -> CHOIX:se [ taillabel ="\nFin délai inactif " ]; + + REGLE:sw -> CHOIX:se [ headlabel ="\n Fin délai\n inactif" ]; REGLE:s -> DUREE:n [ taillabel="\n + " ]; - INCRE:w -> INCRE:nw [ taillabel="- " ]; - INCRE:e -> INCRE:ne [ taillabel=" +" ]; - INCRE:se -> REGLE:ne [ headlabel="\n\n Fin\n délai" ]; - DUREE:w -> DUREE:sw [ taillabel="- \n\n" ]; - DUREE:e -> DUREE:se [ taillabel=" +\n\n" ]; - DUREE:ne -> REGLE:se [ headlabel=" Fin\n délai" ]; + INCRE:w -> INCRE:w [ label="- " ]; + INCRE:n -> INCRE:n [ label="+" ]; + INCRE:se -> REGLE:ne [ label=" Fin délai" ]; + DUREE:w -> DUREE:w [ label="- " ]; + DUREE:s -> DUREE:s [ taillabel="\n +" ]; + DUREE:ne -> REGLE:se [ label=" Fin délai" ]; + INCRE:ne -> SAUVE:n [ label=" Fin délai\n & modif" ]; + DUREE:se -> SAUVE:s [ label=" Fin délai\n & modif" ]; + SAUVE:w -> REGLE:e [ taillabel="- \nou \n+ " ]; { rank = same Veille DUREE }; EXPOS -> Veille [ style=invis]; Veille:e -> DUREE:w [ style=invis]; + REGLE:e -> SAUVE:w [ style=invis]; // n e s w = top right bottom left decorate=true =>line between label & edge } // cluster_ecrans } diff --git a/minuteur/concepdoc/etats_InsoLab.png b/minuteur/concepdoc/etats_InsoLab.png index 83dfd82..7a69577 100644 Binary files a/minuteur/concepdoc/etats_InsoLab.png and b/minuteur/concepdoc/etats_InsoLab.png differ diff --git a/minuteur/displays.h b/minuteur/displays.h index 0770924..d87fa98 100644 --- a/minuteur/displays.h +++ b/minuteur/displays.h @@ -16,7 +16,6 @@ #include #include - // Declaration for SSD1306 display on I2C (SDA, SCL pins) // The pins for I2C are defined by the Wire-library. // Default on RP2040 Zero: SDA GPIO 4 SCL GPIO 5 @@ -26,17 +25,28 @@ #ifdef ESSAIS #define OLED_HEIGHT 64 // OLED display height, in pixels -#define OLED_ADR 0x3D //Address 0x3D/0x3C to 128x64, 0x3C to 128x32 +#define OLED_ADR 0x3C //0x3D //Address 0x3D/0x3C to 128x64, 0x3C to 128x32 #else #define OLED_HEIGHT 32 // OLED display height, in pixels -#define OLED_ADR 0x3C +#define OLED_ADR 0x3C // 0x3C #endif Adafruit_SSD1306 oled(OLED_WIDTH, OLED_HEIGHT, &Wire, OLED_RST); char _oledmsg[32]; // general purpose character buffer +void showInfo(char* l1, char* l2, char* l3) { + oled.clearDisplay(); + oled.setTextSize(1); oled.setTextColor(SSD1306_WHITE); + oled.setCursor(0,0); + sprintf(_oledmsg,"%s",l1); + oled.println(_oledmsg); + sprintf(_oledmsg,"%s",l2); + oled.println(_oledmsg); + sprintf(_oledmsg,"%s",l3); + oled.println(_oledmsg); + oled.display(); +} void showTxt1(uint8_t x, uint8_t y, char* txt) { - oled.clearDisplay(); oled.setTextSize(1); oled.setTextColor(SSD1306_WHITE); oled.setCursor(x,y); // O,0 at top-left corner sprintf(_oledmsg,"CR:%s",txt); @@ -51,23 +61,27 @@ void showText(String l1, String l2) { } void showInit() { - ledInit(); ledRGB(BLANK); //ledRGB(RED); + ledInit(); ledRGB(BLANK);// ledRGB(BLANK); //ledRGB(RED);// if(!oled.begin(SSD1306_SWITCHCAPVCC, OLED_ADR)) { Serial.begin(115200); delay(100); Serial.println(F("SSD1306 allocation failed")); ledRGB(RED); for(;;); // Don't proceed, loop forever } + // setRotation(0)->point(0,0) is close to pin SDA + oled.clearDisplay(); + oled.setRotation(2); // 2->point(0,0) is opposite of pins, 1&3 are vertical //sprintf(_oledmsg, "SSD1306 @ %2d OK", OLED_ADR); oledTxt1(0,0,_oledmsg); delay(100); // Serial.println(_oledmsg); } void showLOGO(int16_t gt) { /*--------- logo on SSD1306 -------------*/ - oled.clearDisplay(); + oled.clearDisplay(); oled.invertDisplay(true); oled.drawBitmap( LOGO_X0, LOGO_Y0,logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, LOGO_COLOR); oled.display(); playRTTTL(sLOGO); - delay(gt); + delay(gt); + oled.invertDisplay(false); } void showTITRE() { // TextSize(2)=>10char, TextSize(1)=>22char, oled.clearDisplay(); @@ -98,9 +112,9 @@ void showEXPOS(uint16_t t, int16_t m) { void showREGLE() { oled.clearDisplay(); oled.setTextColor(SSD1306_WHITE); oled.setCursor(0,0); oled.setTextSize(2); - oled.println(F("Set values")); + oled.println(F("Set times")); oled.setCursor(0,18); oled.setTextSize(1); - sprintf(_oledmsg,"- UVtime, + step time"); oled.println(_oledmsg); + sprintf(_oledmsg," - step, + expo UV"); oled.println(_oledmsg); oled.display(); } void showDUREE(uint16_t t) { @@ -119,4 +133,55 @@ void showINCRE(uint16_t t) { sprintf(_oledmsg,"- less, + more"); oled.println(_oledmsg); oled.display(); } +void showSAUVE(uint16_t t, char* txt) { + oled.clearDisplay(); oled.setTextColor(SSD1306_WHITE); + oled.setCursor(0,0); oled.setTextSize(2); + sprintf(_oledmsg,"%s %3ds",txt,t); oled.println(_oledmsg); + oled.setCursor(0,18); oled.setTextSize(1); + sprintf(_oledmsg,"- quit, + save"); oled.println(_oledmsg); + oled.display(); +} +typedef struct s_iconMvt { + int xp,yp,dy; + } t_iconMvt; + +typedef struct s_sprite { + int count, h, w, x, y, dy; + const unsigned char *bmp; + t_iconMvt *iconsMvt; +} t_sprite ; + + +void initSprite(t_sprite *s, int c, int h, int w, int x, int y, int dy, const unsigned char *bmp,t_iconMvt *iconsMvt) { + //t_iconMvt iconsMvt[c]; //WIP malloc ?? || Arg + s->count=c; s->h=h; s->w=w; s->x=x; s->y=y; s->dy=dy; + for(int i=0; i< s->count; i++) { + iconsMvt[i].xp = random(1 - s->w, OLED_WIDTH); + iconsMvt[i].yp = -s->h; + iconsMvt[i].dy = random(1, 6); + } + s->bmp=bmp; + s->iconsMvt= iconsMvt; +} +void drawSprite(t_sprite *s, Adafruit_SSD1306 d) { + //int8_t iconsMvt[FLOCONS][3]; + d.clearDisplay(); + for(int i=0; i < s->count; i++) { + d.drawBitmap( + s->iconsMvt[i].xp, s->iconsMvt[i].yp, s->bmp, s->w, s->h, SSD1306_WHITE); + } + //d.display(); // Show the display buffer on the screen +} +void updateSprite(t_sprite *s) { + for(int i=0; i < s->count; i++) { + s->iconsMvt[i].yp += s->iconsMvt[i].dy; + // If sprite is off the bottom of the screen... + if (s->iconsMvt[i].yp >= OLED_HEIGHT) { + // Reinitialize to a random position, just off the top + s->iconsMvt[i].xp = random(1 - s->w, OLED_WIDTH); + s->iconsMvt[i].yp = -s->h; // HEIGHT + s->iconsMvt[i].dy = random(1, 6); + } + } // f=0; f< sprites.count; f++) +} #endif // _INSOLAB_DISPLAYS_H_ diff --git a/minuteur/ledRGB.h b/minuteur/ledRGB.h index a4f9223..b0ad180 100644 --- a/minuteur/ledRGB.h +++ b/minuteur/ledRGB.h @@ -19,9 +19,9 @@ Purple #800080 50% 0% 50% 300° 100% 25% 100% 50% 05 (low magenta) #define NUMPIXELS 1 Adafruit_NeoPixel pixels( NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); -enum {NONE, RED, YELLOW, ORANGE, GREEN, BLUE, PINK, FUCHS, BLANK}; +enum {NONE, RED, ROSE, YELLOW, ORANGE, GREEN, BLUE, PINK, FUCHS, BLANK}; int ledColor = NONE; -int ledMax=2; +int ledMax=6; void ledInit() { pixels.begin(); @@ -33,19 +33,21 @@ void ledRGB(int rgb) { switch (rgb) { case RED: pixels.setPixelColor(0, pixels.Color(ledMax, 0, 0)); break; + case ROSE: pixels.setPixelColor(0, pixels.Color(ledMax, 2, 2));// #ffa2a2 + break; case YELLOW: pixels.setPixelColor(0, pixels.Color(ledMax, ledMax, 0)); break; - case ORANGE: pixels.setPixelColor(0, pixels.Color(ledMax, 1, 0)); + case ORANGE: pixels.setPixelColor(0, pixels.Color(ledMax, 3, 0)); break; case GREEN: pixels.setPixelColor(0, pixels.Color(0, ledMax, 0)); break; case BLUE: pixels.setPixelColor(0, pixels.Color(0, ledMax, ledMax)); // AQUA break; - case PINK: pixels.setPixelColor(0, pixels.Color(1,0,3)); // (1,0,2)); + case PINK: pixels.setPixelColor(0, pixels.Color(6,0,8)); // (1,0,2)); break; // pink color (255, 192, 203) deep pink (255, 20, 147) case FUCHS: pixels.setPixelColor(0, pixels.Color(ledMax,0,ledMax)); // FUCHSIA break; - case BLANK: pixels.setPixelColor(0, pixels.Color(1, 1, 1)); + case BLANK: pixels.setPixelColor(0, pixels.Color(4, 4, 4)); break; case NONE: pixels.setPixelColor(0, pixels.Color(0, 0, 0)); break; @@ -58,17 +60,13 @@ void ledScale(int rgb, int first, int aim, int inc, int period) { i = i + inc; switch (rgb) { case RED: - pixels.setPixelColor(0, pixels.Color(i, 0, 0)); - break; + pixels.setPixelColor(0, pixels.Color(i, 0, 0)); break; case GREEN: - pixels.setPixelColor(0, pixels.Color(0, i, 0)); - break; + pixels.setPixelColor(0, pixels.Color(0, i, 0)); break; case BLUE: - pixels.setPixelColor(0, pixels.Color(0, 0, i)); - break; + pixels.setPixelColor(0, pixels.Color(0, 0, i)); break; case BLANK: - pixels.setPixelColor(0, pixels.Color(i, i, i)); - break; + pixels.setPixelColor(0, pixels.Color(i, i, i)); break; } pixels.show(); delay(period); } while (i != aim ); diff --git a/minuteur/minuteur.ino b/minuteur/minuteur.ino index bbdaf28..6190b6b 100644 --- a/minuteur/minuteur.ino +++ b/minuteur/minuteur.ino @@ -30,36 +30,97 @@ - minus decrement step value - plus increment step value - return to caller on time out + * Sleep mode not stable, forum at : + "https://github.com/earlephilhower/arduino-pico/issues/345" -----------------------------------------------------------------------*/ #define BUTTONPLUS 14 // PullUp 10K I=.33 mA #define BUTTONMINUS 15 // PullUp 10K I=.33 mA #define RELAY 27 // Must be < 4mA -#define PIEZO 28 // Used by anyrtttl.h in bitmaps.h +#define PIEZO 8 // Used by anyrtttl.h in bitmaps.h /* I2C SDA & CLK PullUp 2*10K I=.66 mA Sur le RP2040 le défaut du courant de sortie est limité à 4mA/broche IO, C'est configurable par logiciel pour atteindre 2mA, 8mA ou 12mA. Le courant maximal combiné que toutes les broches GPIO peuvent sourcer ou absorber est limité à 50 mA. Au total le courant total doit être < à 50mA. */ +//#define SENSOR_HALL +#define S_HALL 7 // Sense Hall sensor //#define ESSAIS -enum screen_t {sLOGO,sTITRE,sCHOIX,sEXPOS,sREGLE,sDUREE,sINCRE,sNONE}; +enum screen_t {sLOGO,sTITRE,sCHOIX,sEXPOS,sREGLE,sDUREE,sINCRE,sSAUVE,sVEILLE,sNONE}; #ifdef ESSAIS int16_t defaultTime=80, stepTime=5, timeOut=3; // expo & setting time +int16_t snoozeTimeOut=6; #else -int16_t defaultTime=180, stepTime=10, timeOut=2; +int16_t defaultTime=180, stepTime=10, timeOut=4; +int16_t snoozeTimeOut=60; //60 #endif -int16_t greetTime=1000; +int16_t greetTime=2000; // display limit to 999s => 16mn 39s volatile uint16_t setTime=defaultTime; -volatile uint16_t downTime; // count down time +volatile uint16_t downTime; // count down time +volatile uint16_t lastSetTime, lastStepTime, time2save=0; +volatile boolean plusPushed=false; volatile boolean minusPushed=false; +char sMsg[16]; screen_t screen=sTITRE; +#include #include "displays.h" // Oled functions & led RGB #include "pt.h" // proto threads //#include "scroll.h" // circular buffer for displays +#define h42 0x2A +#define h43 0x2B +#define add42 254 +#define add43 255 /*----------------- CPU 0 ---------------------------------*/ void die() {ledRGB(RED); for(;;); } -void setup() { showInit(); showLOGO(greetTime); ledRGB(GREEN); +bool isRamSet() { + byte val1,val2; + EEPROM.begin(256); + //clearRAM(); + val1 = EEPROM.read(add42); + val2 = EEPROM.read(add43); + if (val1==h42 && val2==h43) return true; // allready writed + EEPROM.write(add42, h42); // 42 + EEPROM.write(add43, h43); // 43 + EEPROM.put(0, setTime); + EEPROM.put(4, stepTime); + EEPROM.commit(); // WIP? if (EEPROM.commit()) { do something ? } + return false; +} +void SetTime2RAM() { + EEPROM.put(0, setTime); EEPROM.commit(); +} +void StepTime2RAM() { + EEPROM.put(4, stepTime); EEPROM.commit(); +} +void clearRAM() { + for(int addr = 0; addr < 256; addr++) { + EEPROM.write(addr, 0); + } + EEPROM.commit(); +} +void setup() { + showInit(); + sprintf(sMsg,"Value"); + // read memory + if (isRamSet()) { // setting values to be found in memory + EEPROM.get(0, setTime); + EEPROM.get(4, stepTime); + #ifdef ESSAIS + char l1[16], l2[16], l3[16]; + sprintf(l1,"RAM time values"); + sprintf(l2,"set: %3ds",setTime); + sprintf(l3,"step: %3ds",stepTime); + showInfo(l1, l2, l3); + delay(5000); + #endif + } + // EEPROM.end(); + lastSetTime=setTime; + lastStepTime=stepTime; + showLOGO(greetTime); + minusPushed=false; plusPushed=false; // in case button pushed while LOGO + ledRGB(GREEN); } void loop() { // CPU 0 dedicated to refresh display // TODO not recall screen if values did not change @@ -70,23 +131,31 @@ void loop() { // CPU 0 dedicated to refresh display case sREGLE : showREGLE(); break; case sDUREE : showDUREE(setTime); break; case sINCRE : showINCRE(stepTime); break; - default : ledRGB(RED); delay(3000); break; // Code error + case sSAUVE : showSAUVE(time2save,sMsg); break; + case sVEILLE : delay(100); break; // snooze screen + case sNONE : delay(100); break; // nothing to change yet, waiting for next screen + default : ledRGB(RED); delay(6000); break;// Code error } delay(100); } /*----------------- CPU 1 ---------------------------------*/ // ProtoThreads local continuation structure -static pt_t pMINUS, pPLUS, pTITRE, pCHOIX, pEXPOS, pREGLE, pDUREE, pINCRE; -volatile boolean plusPushed=false; volatile boolean minusPushed=false; +static pt_t pMINUS,pPLUS,pALARM,pTITRE,pCHOIX,pEXPOS, + pREGLE,pDUREE,pINCRE,pSAUVE,pVEILLE; void setup1() { // CPU 1 to manage buttons // ProtoThreads continuation structure is set to 0 - PT_INIT(&pMINUS); PT_INIT(&pPLUS); + PT_INIT(&pMINUS); PT_INIT(&pPLUS); PT_INIT(&pALARM); PT_INIT(&pTITRE); PT_INIT(&pCHOIX); PT_INIT(&pEXPOS); PT_INIT(&pREGLE); PT_INIT(&pINCRE); PT_INIT(&pDUREE); + PT_INIT(&pSAUVE); PT_INIT(&pVEILLE); // IO pinMode(BUTTONMINUS, INPUT_PULLUP); pinMode(BUTTONPLUS, INPUT_PULLUP); pinMode(RELAY, OUTPUT); digitalWrite(RELAY, LOW);delay(500); + +#ifdef SENSOR_HALL + pinMode (S_HALL, INPUT_PULLUP); // Enable pull-up as sensor output is open collector +#endif } static PT_THREAD(pPlus(pt_t *lc)) { // OK and avoid bounces @@ -105,9 +174,22 @@ static PT_THREAD(pMinus(pt_t *lc)) { } PT_END(lc); } +static PT_THREAD(pAlarm(pt_t *lc)) { //WIP + PT_BEGIN(lc); + // PT_WAIT_UNTIL(lc, (screen==sEXPOS) ); + if (digitalRead(S_HALL)) + ledRGB(RED); + else + ledRGB(GREEN); + PT_DELAY(lc, 400); // reading hall sensor + // PT_WAIT_UNTIL(lc, digitalRead(S_HALL));// Pullup pin: switch <=> magnet + // digitalWrite(RELAY, LOW ); } + PT_END(lc); +} static PT_THREAD(pTitre(pt_t *lc)) { PT_BEGIN(lc); - PT_WAIT_UNTIL(lc, (screen==sTITRE)); + PT_WAIT_UNTIL(lc, (screen==sTITRE)); + ledRGB(GREEN); PT_WAIT_UNTIL(lc, (plusPushed || minusPushed )); minusPushed=false; plusPushed=false; screen=sCHOIX; @@ -115,36 +197,41 @@ static PT_THREAD(pTitre(pt_t *lc)) { PT_END(lc); } static PT_THREAD(pChoix(pt_t *lc)) { // TODO sleep & wake up + static unsigned long ttl,to= snoozeTimeOut * 1000; PT_BEGIN(lc); PT_WAIT_UNTIL(lc, (screen==sCHOIX)); ledRGB(ORANGE); - PT_WAIT_UNTIL(lc, (plusPushed || minusPushed ) ); + minusPushed=false; plusPushed=false; + ttl=millis()+to; + PT_WAIT_UNTIL(lc, (plusPushed || minusPushed || (millis() > ttl) ) ); if (minusPushed) { minusPushed=false; screen=sEXPOS; } if (plusPushed) { plusPushed=false; screen=sREGLE; } + if (millis() > ttl) screen=sVEILLE; //screen=sTITRE; // PT_DELAY(lc, 100); PT_END(lc); } static PT_THREAD(pExpos(pt_t *lc)) { // run count down UV light OK PT_BEGIN(lc); - PT_WAIT_UNTIL(lc, (screen==sEXPOS) ); + PT_WAIT_UNTIL(lc, (screen==sEXPOS) ); ledRGB(PINK); downTime = setTime; playRTTTL(sCHOIX); digitalWrite(RELAY, HIGH); minusPushed=false; plusPushed=false; do { // count down loop - // playRTTTL(sCOUNT); send flag to CPU 0 ? or non blocking RTTTL if (plusPushed) { plusPushed=false; if (downTime < 1000 - stepTime) downTime += stepTime; } - PT_DELAY(lc, 800); + PT_DELAY(lc, 600); downTime -=1; if (minusPushed) { minusPushed=false; downTime = 0; } - PT_DELAY(lc, 200); + PT_DELAY(lc, 310); + playClk(); // this take ~100ms } while ( downTime > 0); digitalWrite(RELAY, LOW ); screen=sCHOIX; + ledRGB(ORANGE); playRTTTL(sEXPOS); PT_END(lc); } @@ -167,6 +254,7 @@ static PT_THREAD(pIncre(pt_t *lc)) { // OK PT_BEGIN(lc); PT_WAIT_UNTIL(lc, (screen==sINCRE) ); ledRGB(BLUE); + lastStepTime = stepTime; PT_DELAY(lc, 1000); ttl=millis()+to; minusPushed=false; plusPushed=false; @@ -182,8 +270,10 @@ static PT_THREAD(pIncre(pt_t *lc)) { // OK if (stepTime >1) stepTime-= 1 ; ttl=millis()+to; } - if (millis() > ttl) screen=sREGLE; + if (millis() > ttl) screen=sNONE; } while (screen==sINCRE); + if (lastStepTime == stepTime) screen=sREGLE; + else { sprintf(sMsg,"Step:"); screen=sSAUVE; } PT_END(lc); } static PT_THREAD(pDuree(pt_t *lc)) { // OK @@ -191,6 +281,7 @@ static PT_THREAD(pDuree(pt_t *lc)) { // OK PT_BEGIN(lc); PT_WAIT_UNTIL(lc, (screen==sDUREE) ); ledRGB(FUCHS); + lastSetTime = setTime; PT_DELAY(lc, 1000); ttl=millis()+to; do { @@ -205,47 +296,121 @@ static PT_THREAD(pDuree(pt_t *lc)) { // OK if (setTime > stepTime) setTime -= stepTime ; ttl=millis()+to; } - if (millis() > ttl) screen=sREGLE; + if (millis() > ttl) screen=sNONE; } while (screen==sDUREE); + if (lastSetTime == setTime) screen=sREGLE; + else { sprintf(sMsg,"Time:"); screen=sSAUVE; } PT_END(lc); } +static PT_THREAD(pSauve(pt_t *lc)) { // + static unsigned long ttl, to; + to = (timeOut+4) * 1000; + PT_BEGIN(lc); + PT_WAIT_UNTIL(lc, (screen==sSAUVE) ); + if (lastSetTime != setTime) time2save=setTime; // value for screen sSAUVE + else if (lastStepTime != stepTime) time2save=stepTime; + ledRGB(ROSE); + PT_DELAY(lc, 1000); + ttl=millis()+to; + do { + PT_WAIT_UNTIL(lc, (plusPushed || minusPushed || (millis() > ttl)) ); + if (plusPushed) { + if (lastSetTime != setTime) SetTime2RAM(); + if (lastStepTime != stepTime) StepTime2RAM(); + sprintf(sMsg,"done"); + PT_DELAY(lc, 2000); + screen=sREGLE; + } + if (millis() > ttl || minusPushed) screen=sREGLE; + } while (screen==sSAUVE ); + time2save=0; + PT_END(lc); +} + +static PT_THREAD(pVeille(pt_t *lc)) { // OK and avoid bounces + static int8_t f, icons[FLOCONS][3]; + PT_BEGIN(lc); + PT_WAIT_UNTIL(lc, (screen==sVEILLE)); + ledRGB(NONE); + for(f=0; f< FLOCONS; f++) { + icons[f][XPOS] = random(1 - SNOOZE_WIDTH, oled.width()); + icons[f][YPOS] = -SNOOZE_HEIGHT; + icons[f][DELTAY] = random(1, 6); + } + do { + oled.clearDisplay(); + for(f=0; f< FLOCONS; f++) { // ~ 10 ok for this screen + oled.drawBitmap( + icons[f][XPOS], icons[f][YPOS], flake_bmp, + SNOOZE_WIDTH, SNOOZE_HEIGHT, SSD1306_WHITE); + } + PT_DELAY(lc, 80); + if (!(plusPushed || minusPushed)) { + oled.display(); + PT_DELAY(lc, 80); + // Then update coordinates of each icon + for(f=0; f< FLOCONS; f++) { + icons[f][YPOS] += icons[f][DELTAY]; + // If snowflake is off the bottom of the screen... + if (icons[f][YPOS] >= oled.height()) { + // Reinitialize to a random position, just off the top + icons[f][XPOS] = random(1 - SNOOZE_WIDTH, oled.width()); + icons[f][YPOS] = -SNOOZE_HEIGHT; + icons[f][DELTAY] = random(1, 6); + } + //PT_DELAY(lc, 100); + } // f=0; f< NUMFLAKES; f++) + } + } while (!(plusPushed || minusPushed )); + minusPushed=false; plusPushed=false; + oled.clearDisplay(); + PT_DELAY(lc, 200); + screen=sTITRE; //sCHOIX;// + PT_END(lc); // to try: exit & return flag ? +} + +#define ICONS 4 +t_iconMvt icons[ICONS]; +t_sprite sprite; + +static PT_THREAD(pBugVeille(pt_t *lc)) { // OK and avoid bounces + PT_BEGIN(lc); + PT_WAIT_UNTIL(lc, (screen==sVEILLE)); + ledRGB(NONE); + + initSprite(&sprite,ICONS,16,16,0,1,2, flake_bmp, icons); // load values to sprite + do { + drawSprite(&sprite, oled); + PT_DELAY(lc, 80); + if (!(plusPushed || minusPushed)) { + oled.display(); + PT_DELAY(lc, 80); + updateSprite(&sprite); // update coordinates of each sprite + } + } while (!(plusPushed || minusPushed )); + + minusPushed=false; plusPushed=false; + oled.clearDisplay(); + PT_DELAY(lc, 200); + screen=sCHOIX;// sTITRE; // + PT_END(lc); // to try: exit & return flag ? +} void loop1() { // CPU 1 dedicated to run threads pMinus (&pMINUS); // process minus button pPlus (&pPLUS); // process plus button + // pAlarm (&pALARM); // WIP pTitre (&pTITRE); // process screen TITRE pChoix (&pCHOIX); // process screen CHOIX pExpos (&pEXPOS); // process screen EXPOS pRegle (&pREGLE); // process screen REGLE pIncre (&pINCRE); // process screen INCRE pDuree (&pDUREE); // process screen DUREE + pSauve (&pSAUVE); // process screen SAUVE + pVeille(&pVEILLE); // process screen saver + } /* -* provisions - #include -v -void setup() { - EEPROM.begin(512); - // write a 0 to all 512 bytes of the EEPROM - for (int i = 0; i < 512; i++) { - EEPROM.write(i, 0); - } - // turn the LED on when we're done - pinMode(13, OUTPUT); - digitalWrite(13, HIGH); - EEPROM.end(); -} -void loop() { - static int x = 0; - Serial.printf("C1: Stay on target...\n"); - val++; - if (++x < 10) { - EEPROM.begin(512); - EEPROM.write(0,x); - EEPROM.commit(); - } - delay(1000); -} * code debug Serial.begin(115200); delay(500); Serial.printf("CPU 0 on\n"); Serial.printf("CPU 1 on\n"); diff --git a/schéma/pcb_mcu.png b/schéma/pcb_mcu.png new file mode 100644 index 0000000..05d2679 Binary files /dev/null and b/schéma/pcb_mcu.png differ diff --git a/schéma/schema_minuteur.fzz b/schéma/schema_minuteur.fzz index 2c7e582..cd6146d 100644 Binary files a/schéma/schema_minuteur.fzz and b/schéma/schema_minuteur.fzz differ