Avatar for allObjects

allObjects

Member since Jul 2014 • Last active Jun 2023

Espruino makes IoT as easy as 123!

Most recent activity

  • in Bangle.js
    Avatar for allObjects

    Nice, clean layout.

  • in Bangle.js
    Avatar for allObjects

    Great elaboration... Actually, it could be around the moon... (taking the moon a bit more out of and up from the day stripe, make the day a bit narrower provides the extra pixels for a moon 'lander' to orbit w/ a trace the moon). I understand and agree that the redraw should not be complicated when wanting to remove an element. What I do to remove an element, I have it on a plain background and redraw it with the background color.

    I know that the moon is already pretty small because it has to fit into the day space. Have a 'second pulsing' is just another thing alive when really wanted to see it... it is less for the timing but more for the show and 'feel' a rhythm.

    I did some fancy thing with the 'stopping and jumping/restarting second hand when starting a new minute, like all Swiss Federal Railway clocks do - see Swiss Federal Railway Clock modeled w/ Circular Gauges.

    PS: All kinds of walks of life get involved and conversation titles look a-like: New to Bangle.js and Espruino. Need help with graphics.

  • in Bangle.js
    Avatar for allObjects

    Nice... piece of art!

    Do you have something that shows the second or half second on certain events, like tapping the screen? For example a growing circle segment starting at 0 seconds, grow up to current second, and then tick for a few more seconds, and then fade away?

  • in Bangle.js
    Avatar for allObjects

    Years ago I did some calibration coding when exploring resistive touch screen on these very available 240x320 262k color TFT LCD displays: Touchscreen. Then, the touch screen readings were analog values that went into a formula and delivered the pixels... now it is muchs simpler for the pixel part: the reading already deliver pixels... but timing for touch and drag/swipe may more complex since the screen is much smaller and the touching device is more fuzzy (finger tip vs stylo).

  • in Bangle.js
    Avatar for allObjects

    @ga,

    looking good. Very interesting approach to make a watch face more alive and injecting analog aspects into digital representation.

    Regarding calculation intervals: you can actually have multiple events with different timeout times / interval times going, so that the minimum calculations are executed to save power and extend battery life. Same applies for applying changes to the display: update only what is actually required to be updated. Bangle.js2 is already very fast, much faster than Bangle.js. Display size and color depth and how the display driver is communicating with the processor. Using vector fonts is process intensive. May be you can use a bitmap copy process rather than a drawing process, since the number of character you need are very small, and the variation in size is limited (what's the min and max font size for hr and min?). Storage in Flash EEPROM rather than RAM should provide you enough space to do something like that.

    Checkout out this conversation about setFontCustom bitmap format vs vertical_byte:true - GT24L24A2Y fontchip in F07 fitness tracker

  • in Bangle.js
    Avatar for allObjects

    @ga, looks like your main challenge is switching from environments with theoretically unlimited resources to something that lives on a shoe string budget, almost in evey regard

    display: did you ever do graphics on a 176x176 pixel, 8 colors per pixel display (11KB graphics memory), like bangle.js2? A bit more graphics resource of 240x240 pixel 64K colors? ...no GPU...

    memory: 256KB (64KB) RAM - includes 'OS' (OS is standalone JS - or a JS that includes all OS commands)

    cpu: single core, 64MHz, responsible for just everything that is going on.

    ...and last but not least: execution runs (mainly) on source interpretatively (now there are some faster options for some parts, and compiled, c and assembly can be mixed in).

    It is a mind shift... even when coming for a JS past. Good pre-disposition is having worked with the first - viable for general applications - 8-bit micro processors on the market, where you might have the computing capacity defined by 8-bit CPU with mainy 8 bit registers and a few 16- bit ones for adressing memory, 2-4MHz clocked, 32..64 KB RAM, very simple, frugal OS, and sometimes the screen/character display of 24 lines / 80 characters - monochrome - is memory mapped / part of your RAM. OS and Screen in 10KB, rest free for programs with their data. Storage: 80 or 160KB 8" or 5-1/4" floppy... total 'mass' storage addressability: 60/80..16..1200KB (max not even 'lasting' for a single picture taken with the phone...

    All this said and in mind, it is all just a matter of how smart and targeted/dedicated the implementation is with so much - little - resources.

  • in Bangle.js
    Avatar for allObjects

    The calibration should not accept 'unreasonable' values... as the PALM showed x-es to touch/tap.

  • in Bangle.js
    Avatar for allObjects

    @Q_NErk, you mean peer to peer BT communication between Bangle.js and ESP32? ...where Bangle.js raises the data and an EPS32 collecting it? ...from one or multiple Bangle.js?

  • in Projects
    Avatar for allObjects

    The test code...

    To test a chip output, the wired Pico input is read twice, once with input_pulldown and once with input_pulldown to really detect driven High and Low as well as three-state, high impedance Z. Furthermore, when inputs, addresses or control lines do not matter, the testing goes thru all their permutations to make sure that their state and transition do really not matter. This intense testing is not visible in the output, especially for the last block that does multi-writes and multi-reads. Looking at the nested loops in the code makes though clear that it is not just a write and then a read for each of the 8 bits, but a got 1300 - thirteen hundred tests... (may be I'm paranoid... because all chips I got passed w/ flying colors).

    // MC14599_8B_ADDR_LATCH.js
    // 20230327ao
    //
    // Using pico to test NOS MC14599B 8-Bit Addressable Latches
    //
    var lon = true; // false; // true; // logging is on
    function log() { if (lon) { console.log.apply(console,arguments); } }
    // wire connections
    //  ic - pico
    var CQ0=A0, CQ1=A1, CQ2=A2, CQ3=A3, CQ4=A4, CQ5=A5, CQ6=A6, CQ7=A7
      , CW_R=B1, CE=B7, CWDS=B8, CRST=B9
      , CA0=B3, CA1=B4, CA2=B5
      , CD=B6 
      , CQ = [CQ7, CQ6, CQ5, CQ4, CQ3, CQ2, CQ1, CQ0]
      , CA = [CA2, CA1, CA0]
      ;
    function setPinModes() {
      // driving the chip controls
      pinMode(CW_R,"output");
      pinMode(CE  ,"output");
      pinMode(CWDS,"output");
      pinMode(CRST,"output");
      // driving the bit latch address lines
      pinMode(CA0,"output");
      pinMode(CA1,"output");
      pinMode(CA2,"output");
      // reading the 8B latches
      pinMode(CQ0,"input");
      pinMode(CQ1,"input");
      pinMode(CQ2,"input");
      pinMode(CQ3,"input");
      pinMode(CQ4,"input");
      pinMode(CQ5,"input");
      pinMode(CQ6,"input");
      pinMode(CQ7,"input");
      // reading / writing the chip data (preset)
      pinMode(CD,"input");
    }
    
    function hex(v) { return ((v>15) ?
      hex(v>>4) : "")+"0123456789ABCDEF".charAt(v&15); } // hex...
    function hep(v,ds) { // hex, digits (w/ blank padding up to ds)
      return ("        "+hex(v)).substr(-ds); }
    function lep(v,ds) { // hex, digits (w/ 0 padded up to ds)
      return ("00000000"+hex(v)).substr(-ds); }
    
    var tMax = 1 // test repetitions
      , tCnt = 0
      , passed, somePassed, someFailed
      ;
    var tester =
    { test: function() { // tester object (tool)
        log(++tCnt);
        this.tResetLatch();
        this.tResetData();
        this.tChipDisableLatch(true);  // onReset
        this.tChipDisableData( true);  // onReset
        this.tChipDisableLatch(false); // w all 0 then 1 - tests all to 1
        this.tChipDisableData( false); // w all 0 then 1 - tests all to 1
        this.tChipDisableLatch(false); // w all 0 then 1 - tests all to 0
        this.tChipDisableData( false); // w all 0 then 1 - tests all to 0
        this.tWrite01010();
        this.tWriteRead01010();
      }
    
    // test reset for latch
    // - expects nothing
    // - leaves -+CE, -+W_R, +WDS, -+AX(3), -+RST
    , tResetLatch: function() {
        log("\ntResetLatch","<=====");
        var td = "tResetLatch"
          , ps=[CE,CW_R,CWDS,CA2,CA1,CA0], px, v, r, t
          , p=true, passedCnt=0; failedCnt=0;
        this.dIPM(); // data input to avoid any contention
        CRST.set();
        t = 0;
        for (v = 0; v <= 1; v++) {
          this.lIPM(v);
          for (px = 0; px <= 0x3F; px++) {
            digitalWrite(ps,px);
            if ((r = digitalRead(CQ)) !== t) { // 0x00 
              log(td,"FAILED",v,hep(px,2),": 00",lep(r,2));
              p = false; failedCnt++;
            } else {
              passedCnt++;
            }
        } }
        if (p) { 
          log("-- "+td+" ok");
        } else {
          log("-- "+td+": passed =",passedCnt,", FAILED =",failedCnt);
        }
        passed &= p;
        digitalWrite(ps,0b001000);
        CRST.reset();
       }
    
    // test reset for data
    // - expects nothing
    // - leaves -+CE, -+W_R, +WDS, -+AX(3), -+RST
    , tResetData: function() {
        log("\ntResetData","<=====");
        var td = "tResetData"
          , ps=[CE,CW_R,CWDS,CA2,CA1,CA0], px, v, w, r, t
          , p=true, passedCnt=0; failedCnt=0;
        this.dIPM(); // data input to avoid any contention
        CRST.set();
        for (v = 0; v <= 1; v++) {
          this.lIPM(v); t = v * 0xFF;
          for (px = 0; px <= 0x3F; px++) {
            for (w = 0; w <= 1; w++) {
              this.dIPM(w); t = w;
              if ((r = digitalRead(CD)) !== t) { // high imp Z
                log(td,"FAILED",v,hep(px,2),":",t,r);
                p = false; failedCnt++;
              } else {
                passedCnt++;
              }
            }
        } }
        if (p) { 
          log("-- "+td+" ok");
        } else {
          log("-- "+td+": passed =",passedCnt,", FAILED =",failedCnt);
        }
        passed &= p;
        digitalWrite(ps,0b001000);
        CRST.reset();
       }
    
    // test chip -+enable (disable) for latch
    // - expects nothing when w/ rst, otherwis -+CE, -+W_R, +WDS, -+RST
    // - leaves -+CE, -+W_R, +WDS, -+AX(3), -+RST conditional use
    , tChipDisableLatch: function(withRst) {
        log("\ntChipDisableLatch",(withRst)?" WITH ":"WITHOUT","RST","<=====");
        var td = "tChipDisableLatch"+((withRst)?"AftReset­":"InGeneral")
          , ps=[CW_R,CWDS,CA2,CA1,CA0], px, u, v, r, t, tt
          , p=true, passedCnt=0; failedCnt=0;
        this.dIPM(); // data input to avoid any contention
        if (withRst) CRST.set();
        CE.reset(); // -+CE disable
        if (withRst) CRST.reset();
        for (u = 0; u <= 1; u++) {
          if ( ! withRst || u === 0) {
            t = u * 0xFF; tt = ": " + lep(t,2);
            if ( ! withRst) this.allOut(u);
            for (v = 0; v <= 1; v++) {
              this.lIPM(v);
              for (px = 0; px <= 0x2F; px++) {
                digitalWrite(ps,px);
                if ((r = digitalRead(CQ)) !== t) { // high imp Z
                  log(td," FAILED",u,v,hep(px,2),tt,lep(r,2));
                  p = false; failedCnt++;
                } else {
                  passedCnt++;
       } } } } }
       if (p) { 
          log("-- "+td+" ok");
        } else {
          log("-- "+td+": passed =",passedCnt,", FAILED =",failedCnt);
        }
        passed &= p;
        digitalWrite(ps,0b001000);
       }
    
    // test chip -enable (disable) for data
    // - expects nothing
    // - leaves -+CE, -+W_R, +WDS, -+AX(3), -+RST conditional use
    , tChipDisableData: function(withRst) {
        log("\ntChipDisableData",(withRst)?" WITH ":"WITHOUT","RST","<=====");
        var td = "tChipDisableData"+((withRst)?"AftReset"­:"InGeneral")
          , ps=[CW_R,CWDS,CA2,CA1,CA0], px, v, w, r, t
          , p=true, passedCnt=0; failedCnt=0;
        this.dIPM(); // data input to avoid any contention
        if (withRst) CRST.set();
        CE.reset(); // -+CE disable
        if (withRst) CRST.reset();
        for (u = 0; u <= 1; u++) {
          if ( ! withRst || u === 0) {
          if ( ! withRst) this.allOut(u);
            for (v = 0; v <= 1; v++) {
              this.lIPM(v);
              for (px = 0; px <= 0x2F; px++) {
                for (w = 0; w <= 1; w++) {
                  this.dIPM(w); t = w;
                  if ((r = digitalRead(CD)) !== w) {
                    log(td," FAILED",v,hep(px,2),w,r);
                    p = false; passedCnt++;
                  } else {
                    passedCnt++;
        } } } } } }
        if (p) { 
          log("-- "+td+" ok");
        } else {
          log("-- "+td+": passed =",passedCnt,", FAILED =",failedCnt);
        }
        passed &= p;
        digitalWrite(ps,0b001000);
      }
    
    // test write individual outputs
    // - expects -+CE, -+W_R, +WDS, -+AX(3), -+RST
    // - leaves -+CE, -+W_R, +WDS, -+AX(3), -+RST not in use
    , tWrite01010() {
        log("\ntWrite01010","<=====");
        var td = "tWrite01010"
          , vs = [0,1,0,1,0]
          , ps=[CW_R,CWDS,CA2,CA1,CA0]
          , addr, t = 1, w, vx, v, r
          , p=true, passedCnt=0; failedCnt=0;
        this.allOut(0); passed &= this.validateQX(td,"setup QX=00",0);
        for (addr = 0; addr <=7; addr++) {
          for (vx = 0; vx <= 4; vx++) {
            v = vs[vx]; w = v * t;
            this.write(addr,v);
            if ( ! this.validateQX(td,"write",w)) {
              log(td,"FAILED",addr,v,":",lep(w,2),lep(­digitalRead(CQ),2));
              p = false; failedCnt++;
            } else {
              passedCnt++;
            }
          }
          t = t<<1;
        }
        if (p) { 
          log("-- "+td+" ok");
        } else {
          log("-- "+td+": passed =",passedCnt,", FAILED =",failedCnt);
        }
        passed &= p;
        digitalWrite(ps,0b001000);
      }
    
    // test write individual outputs
    // - expects -+CE, -+W_R, +WDS, -+AX(3), -+RST
    // - leaves -+CE, -+W_R, +WDS, -+AX(3), -+RST not in use
    , tWriteRead01010() {
        log("\ntWriteRead01010","<=====");
        var td = "tWriteRead01010"
          , vs = [0,1,0,1,0]
          , ps=[CW_R,CWDS,CA2,CA1,CA0]
          , wddr, rddr, t = 1, w, vx, v, r
          , p=true, passedCnt=0; failedCnt=0;
        this.allOut(0); passed &= this.validateQX(td,"setup QX=00",0);
        for (wddr = 0; wddr <=7; wddr++) {
          for (vx = 0; vx <= 4; vx++) {
            v = vs[vx]; w = v * t;
            this.write(wddr,v);
            if ( ! this.validateQX(td,"write",w)) {
              log(td,"write FAILED, skip read",wddr,v,":",lep(w,2),lep(digitalRea­d(CQ),2));
              p = false; failedCnt += 8;
            } else {
              // log(td,"write OK, do read",wddr,v,":",lep(w,2),lep(digitalRea­d(CQ),2));
              for (rddr = 0; rddr <= 7; rddr++) {
                if (rddr === wddr) { // exp v
                  r = this.read(rddr,w = v);
                } else {
                  r = this.read(rddr,w = 0);
                }
                if (r !== w) {
                  log(td,"read FAILED",wddr,rddr,v,":",w,r);
                  p = false; failedCnt++;
                } else {
                  // log(td,"read OK",wddr,rddr,v,":",t,r);
                  passedCnt++;
                }
              }
            }
          }
          t = t<<1;
        }
        if (p) { 
          log("-- "+td+" ok");
        } else {
          log("-- "+td+": passed =",passedCnt,", FAILED =",failedCnt);
        }
        passed &= p;
        digitalWrite(ps,0b001000);
      }
    
    // setup latch QX for input w/ pull-up or pull-down
    , lIPM: function(falseOrTrue) { // input _pulldown / _pullup
        var pull = "input_" + ((falseOrTrue) ? "pullup" : "pulldown");
        for (var p=0; p<8; p++) { pinMode(CQ[p],pull); } }
    
     // setup data QD for input w/ pull-up or pull-down
    , dIPM: function(falseOrTrue) { // input _pulldown / _pullup
        pinMode(CD,"input_" + ((falseOrTrue) ? "pullup" : "pulldown")); }
    
     // setup data QD for input w/ high imp Z
    , dIM: function() { pinMode(CD,"input"); }
    
     // setup data QD for output
    , dOM: function() { pinMode(CD,"output"); }
    
    // set all latches to value
    , allOut(v) {
        log("allOut(",v,") <-----");
        for (var a=0; a<=7; a++) this.write(a,v);
        log("allOut:",v,lep(digitalRead(CQ),2));­
      }
    
    // write at addr data bit
    // expects -+CE, -+W_R, +WDS, -+RST (not used)
    // leaves -+CE, -+W_R, +WDS, -+RST
    , write(addr,data) {
        CWDS.set();
        digitalWrite(CA,addr & 7);
        CW_R.set();
        this.dOM();
        digitalWrite(CD,data & 1);
        CE.set();
        CWDS.reset();
        CWDS.set();
        this.dIM();
        CW_R.reset();
        CE.reset();
      }
    
    // read at addr data bit (w/ opposite pull when exp !== null - false/true/0/1)
    // expects -+CE, -+W_R, +WDS, -+RST (not used)
    // leaves -+CE, -+W_R, +WDS, -+RST (uses only +CE)
    , read(addr,exp) {
        var r;r = (exp === undefined) ? undefined : ! exp;
        digitalWrite(CA,addr & 7);
        if ((r = (exp === undefined) ? undefined : ! exp) === undefined) {
          this.dIM();
        } else {
          this.dIPM(r);
        }
        CE.set();
        r = digitalRead(CD);
        CE.reset();
        this.dIM();
        return r;
      }
    
    // validate QX === t w/ pulldown and pullup
    , validateQX: function(td, det, t) {
        var p = true;
        this.lIPM(0);
        if ((r = digitalRead(CQ)) !== t) {
          log(td, det, "FAILED", lep(t,2), lep(r,2));
          p = false; }
        this.lIPM(1);
        if ((r = digitalRead(CQ)) !== t) {
          log(td, det, "FAILED", lep(t,2), lep(r,2));
          p = false; }
        return p;
      }
    
    }
    ;
    
    function onInit() {
      setPinModes();
      somePassed = false; someFailed = false;
      var tIId = setInterval(function() {
           LED1.reset(); LED2.reset();
           passed = true;
           tester.test();
           if (passed) {
             LED2.set(); somePassed = true;
           } else {
             LED1.set(); someFailed = true;
           }
           if (tCnt>=tMax) {
             clearInterval(tIId);
             if (somePassed) { LED2.set(); }
             if (someFailed) { LED1.set(); }
           }
        },750);
    }
    
    setTimeout(onInit,999); // dev only; remove before upload for save()
    

    A corresponding ouput:

    >
     ____                 _
    |  __|___ ___ ___ _ _|_|___ ___
    |  __|_ -| . |  _| | | |   | . |
    |____|___|  _|_| |___|_|_|_|___|
             |_| espruino.com
     2v17 (c) 2021 G.Williams
    >
    1
    tResetLatch <=====
    -- tResetLatch ok
    tResetData <=====
    -- tResetData ok
    tChipDisableLatch  WITH  RST <=====
    -- tChipDisableLatchAftReset ok
    tChipDisableData  WITH  RST <=====
    -- tChipDisableDataAftReset ok
    tChipDisableLatch WITHOUT RST <=====
    allOut( 0 ) <-----
    allOut: 0 00
    allOut( 1 ) <-----
    allOut: 1 FF
    -- tChipDisableLatchInGeneral ok
    tChipDisableData WITHOUT RST <=====
    allOut( 0 ) <-----
    allOut: 0 00
    allOut( 1 ) <-----
    allOut: 1 FF
    -- tChipDisableDataInGeneral ok
    tChipDisableLatch WITHOUT RST <=====
    allOut( 0 ) <-----
    allOut: 0 00
    allOut( 1 ) <-----
    allOut: 1 FF
    -- tChipDisableLatchInGeneral ok
    tChipDisableData WITHOUT RST <=====
    allOut( 0 ) <-----
    allOut: 0 00
    allOut( 1 ) <-----
    allOut: 1 FF
    -- tChipDisableDataInGeneral ok
    tWrite01010 <=====
    allOut( 0 ) <-----
    allOut: 0 00
    -- tWrite01010 ok
    tWriteRead01010 <=====
    allOut( 0 ) <-----
    allOut: 0 00
    -- tWriteRead01010 ok
    > 
    
Actions