-
When you combine this with Software Buttons - Many buttons from just one hardware button you can send more than just one key short cut...
-
Memory is always and issue: queuing image buffers for partial update could quickly throw you into out-of-memory hell.
Going w/ the queueing idea, I suggest the following when a) is possible:
a) Have a full buffer for the EDispay
b) Use the Graphics to update the buffer and queue the info about rectangle that has been changed
c) Have a worker that selects and transfers by the queued information from the buffer to the EDisplayCaveats:
- Regarding b) I don't know if the current Graphics implementation provides you with the rectangle information after a draw command. Depending of such implementation, it could feed that queue. May be on creation of the Graphics object, an additional parameter/option could be passed that provides that queue.
- Lot's of small overlapping things, such updating the second hand in an analog clock, could become inefficient. Therefore, the algorithm that selects the rectangle to display could be smarter then just take what is next in queue, and calculate a new rectangle containing multiple rectangles to achieve a higher overall-efficiency.
- Specific draw commands - specially for lines 'around' +45 and -45 degrees - could define multiple rectangles rather than one big one...
I'm not sure if this thread of thought leads somewhere useful... ;-) ... :\ ... :(
Quite some time ago when playing with a gps and a serially connected 320x240 260K color TFT, I ran into the issue of not having enough time between the 1s interval of inputs to update the screen... I resorted to store the gps info and only display where a changes was, and when I run out of time, to skip some of the changes: DIY Marine GPS using enhanced GPS Module, u-blox NEO-6M GPS receiver, and ILI9341 Module controlled 2.8" Color TFT LCD.
- Regarding b) I don't know if the current Graphics implementation provides you with the rectangle information after a draw command. Depending of such implementation, it could feed that queue. May be on creation of the Graphics object, an additional parameter/option could be passed that provides that queue.
-
I don't see
learn the "gramma" of 100+ languages
to be the issue here...
It is the 'cartesian product' of all the nitty gritty deltas of all the components that have to play nice with each other by code that does not break the 'resources' bank.
Infrastructures and frameworks that can handle the deltas of various hardware platforms are generally very bloated not only in respect to static resources - code memory - but also in respect to dynamic resources - variable memory and cycles - at runtime. Build-time effort left by the side.
Therefore, picking and focusing on (just) a few 'animals' that are 'biologically' compatible is the requirement for (economic) sustainability.
For me, Espruino ecosystem can claim the Guiness World Record for biodiversity, hackability, resourcefulness, robustness,... and is vibrantly alive (has survived many others).
-
Sure... the challenge is syncing to the timings the emitting side uses.
Some 'AI' has to detect over some time what the emitter's times are for short, long, break between 'beeps' and then characters and then words, and then apply it retrospectively. On the Web there is some code that already does this. After initial syncing, adjusting the sync has then to happen continuously.
-
-
-
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.
-
-
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).
-
@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
-
@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.
-
-
@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?
-
The test code...
To test a chip output, the wired Pico input is read twice, once with
input_pulldown
and once withinput_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(digitalRead(CQ),2)); p = false; failedCnt += 8; } else { // log(td,"write OK, do read",wddr,v,":",lep(w,2),lep(digitalRead(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 >
-
This becomes kind a series of examples how Pico comes handy for a lot of different things - see Using Pico to test new old stock (NOS) IC - MC14512 - 8 Channel Data Selector. You may guess where this is going...
But for now, just focusing on this little interesting and quite versatile MC14599 chip from the past: a bit addressable storage of 8 bits with 1-bit wide data bus and 8 bits output port, 1 for each of the stored bits. A bit can be written and read back by 3 address lines. It behaves like Pico GPIO in "output" pin mode.
Compared to the MC14512 - 8 Channel Data Selector - the testing software turned out to be much more complex - no easy way to just use a truth table with data driven logic - but exclusively procedural. With some shoehorning a data drive approach could be construed, but it was just easier to code while exploring the chip's workings.
The next post shows the code and test output.
-
@idobh2, really NICE work!
-
Code for tester:
The code uses a hybrid of declarative and procedural approach to perform the test. It uses the truth table to define a test 'matrix'. Each row defines the the inputs and encoded the expected output. The inputs to the IC to test are arranged/ encoded suitable to write to Espruino Pico pins by an array. Functions the use this data, apply the inputs as outputs, and do some additional iteration or variation of values. The results get written to the console. An output example is attached. Enhancements would be to power the IC and run the test on BTN1 press.
Note the 'renaming' of the pico pins to drive the IC: the Pico 'are named' for the Chip to test - C w/ chip's pin function Name - to make it obvious what is going on in the code.
// MC14512_8CH_SEL.js // 20230311ao // // Using pico to test NOS MC14512B 8-Channel Data Selector // var lon = true; // false; // true; // logging is on function log() { if (lon) { console.log.apply(console,arguments); } } // wire connections // ic - pico var CX0=A0, CX1=A1, CX2=A2, CX3=A3, CX4=A4, CX5=A5, CX6=A6, CX7=A7 , CDIS=B1, CINH=B10 , CSA=B13, CSB=B14, CSC=B15 , CZ=A10 , CX = [CX7, CX6, CX5, CX4, CX3, CX2, CX1, CX0] , CS = [CSC, CSB, CSA] , CC = [CINH, CDIS] ; function setPinModes() { // driving the chip controls pinMode(CINH,"output"); pinMode(CDIS,"output"); // driving the channel address lines pinMode(CSA,"output"); pinMode(CSB,"output"); pinMode(CSC,"output"); // driving the 8 channel inputs pinMode(CX0,"output"); pinMode(CX1,"output"); pinMode(CX2,"output"); pinMode(CX3,"output"); pinMode(CX4,"output"); pinMode(CX5,"output"); pinMode(CX6,"output"); pinMode(CX7,"output"); // reading the chip output (preset) pinMode(CZ,"input"); } // truth table (MSNib = channel #, LSNib = INH,DIS) var tt = [[0x00, 1] // X0 - channels 0..7, inputs ,[0x10, 2] ,[0x20, 4] ,[0x30, 8] ,[0x40, 16] ,[0x50, 32] ,[0x60, 64] ,[0x70,128] // X7 ,[0x02, 0] // 0 - inhibit ,[0x01, -1] // high imp - disable ,[0x03, -1] // high imp - disable ] ; function hex(v) { return ((v>15) ? hex(v>>4) : "")+"0123456789ABCDEF".charAt(v&15); } // hex... function hep(v,ds) { // hex, digits (w/ padding up to ds) return (" "+hex(v)).substr(-ds); } function tvSplit(tv) { // split return([tv[0]>>4, tv[0]&3, tv[1]]); } var tMax = 3 // test repetitions , tCnt = 0 , passed, somePassed, someFailed ; var tester = { test: function() { // tester object (tool) log(++tCnt); for (var i=0; i<tt.length; i++) { // log("["+hex(i)+"]"); if (i<8) { // --- channel X0..X7 this.channel.apply(this,tvSplit(tt[i])); } else if (i==8) { // --- 0 - inhibit this.inhibit.apply(this,tvSplit(tt[i])); } else { // --- high imp - disable ... this.disable.apply(this,tvSplit(tt[i])); // w/ inhibit 0|1 } } } // test channel w/ channel select s, control, value , channel: function(s,c,v) { digitalWrite(CC,c); digitalWrite(CS,s); log("channel",hex(s),this.chkChan(1,v)); log("channel",hex(s),this.chkChan(0,v)); } , chkChan: function(b,v) { var va = ((b)?v:v^255)&255, n, p; digitalWrite(CX,va); pinMode(CZ, (b) ? "input_pulldown" : "input_pullup"); n = digitalRead(CZ); passed &= (p = (n === b)); return ((b)?"H ":"L ")+n+" "+hep(va,2) + ((p) ? " ok" : " FAILED"); } // test inhibit on INH, (-DIS) , inhibit: function(s,c,v) { digitalWrite(CC,c); digitalWrite(CX,255); pinMode(CZ,"input_pullup"); var p = true; for (var j=0;j<8;j++) { if (digitalRead(CZ)) { log("inhibit FAILED on channel ",j); p = false; } } if (p) log("inhibit ok"); passed &= p; } // test disable on DIS , disable: function(s,c,v) { digitalWrite(CC,c); this.chkDis(c,255,0); this.chkDis(c,255,1); this.chkDis(c, 0,0); this.chkDis(c, 0,1); } , chkDis: function(c,v,r) { digitalWrite(CX,v); pinMode(CZ,(r)?"input_pullup":"input_pulldown"); var p = true; for (var j=0;j<8;j++) { if (r !== digitalRead(CZ)) { log("disable w/ inhibit=",(c>>1)," val=",hep(v,2) ," FAILED on channel ",j); p = false; } } if (p) { log("disable w/ inhibit=",(c>>1)," val=",hep(v,2)," ok"); } passed &= 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()
Output:
> ____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |____|___| _|_| |___|_|_|_|___| |_| espruino.com 2v17 (c) 2021 G.Williams > 1 channel 0 H 1 1 ok channel 0 L 0 FE ok channel 1 H 1 2 ok channel 1 L 0 FD ok channel 2 H 1 4 ok channel 2 L 0 FB ok channel 3 H 1 8 ok channel 3 L 0 F7 ok channel 4 H 1 10 ok channel 4 L 0 EF ok channel 5 H 1 20 ok channel 5 L 0 DF ok channel 6 H 1 40 ok channel 6 L 0 BF ok channel 7 H 1 80 ok channel 7 L 0 7F inhibit ok disable w/ inhibit= 0 val= FF ok disable w/ inhibit= 0 val= FF ok disable w/ inhibit= 0 val= 0 ok disable w/ inhibit= 0 val= 0 ok disable w/ inhibit= 1 val= FF ok disable w/ inhibit= 1 val= FF ok disable w/ inhibit= 1 val= 0 ok disable w/ inhibit= 1 val= 0 ok > 2 channel 0 H 1 1 ok channel 0 L 0 FE ok channel 1 H 1 2 ok ..... ... .
-
I got some new old stock (NOS) ICs, and before I used them and get puzzled why my circuitry does not behave as expected, I wanted to test them. It's a functional test, no timing test. Test is repeated as many times as specified. If at the end only the green LED (LED2) is on, then all tests were successful. If red LED (LED1) is on, then at least one test failed. If only the red LED is on, then all tests failed.
The example here is the Motorola CMOS MC14512B - 8 Channel Data Selector.
For details about the IC and the wiring see attached pictures. Codes and console output in second post.
Edit 2023-03-28: This MC14512 got a versatile buddy in crime: Using Pico to test new old stock (NOS) IC - MC14599 - 8 Bit Addressable Latch
-
In a UI context, the long press vs short kick usually initiates an alternate function or a menu to select from a host of alternate functions. It became necessity when - because of Apple (2) - lost the second eye to end up as a single eyed minion. Initially, the mouse started out with 3...
Next issue with touch vs mouse is the loss of continuous 'contact' of the pointing device indicator - and with that the mouse pointer had to go away. Luckily touch w/ move - drag - is introduced.
Back to the long press: this could actually really increase robustness of changing settings. I experience the setting of, for example, elements of time very finicky... may be I do it wrong, but a long press on the item with a pop up that has plenty real estate to have easy usable up/down, cancel/ok controls.
Sometimes the direct control is not worth the trouble it creates, or in other words, and extra touch at the begin and end of an operation is worth to pay to have a robust working operation. This is especially true in the fight of a fat finger on a super tiny and moving touch screen.
-
@Fteacher, I like your comment
I'm restarting the creative (but so tedious for beginners) process of coding.
a lot, especially this part: ...so tedious for beginners
I can tell you that without Espruino / @Gordon's platform, you would not even find a word in the whole universe to describe it...
just saying.
Enjoy the creative writing process... Espruino likes to read your stories and follow them to the tee... so watch what you are asking it for!
-
Use an C routine to extract into a transmit buffer... this is fast and lets you use the the Graphics class for Espruino style drawing and push out the buffer as is. Claiming contiguous memory should not be an issue... (see use of C in Efficiently moving things around in zig-zag Graphics buffer visualized w/ 24/32 bpp displays / neopixel strings. Using this technology you can trigger the update of the display anytime and it can run to its own beat. Used that technology in the same application context: drawing/writing to the Graphics object is event driven and updating the display/reading the Graphics object is event driven. Update you can trigger by time or at application flow specific points where you know that updating the display makes sense. I'm not sure if you use partial update... which I know was tried and shared in the forum, but I cannot recall final conclusions (your fourth color could be used for that - using a bit pattern for the white, red and black colors that share a bit - to determine what zone to update and clear it on update).
Having the drawing and updating the display separated allows optimizing of automated update and at the same time on demand update as the application can control it (fire an event and move on, and update requests can be queued and skipped to do the least number of). Separation also makes it easy to exchange the displays type.
If you are short on memory, doing it inplace? Not sure what you win, because transformation would have to happend before AND after transmission to display.
@MaBe is one of the forum members who has extensive experience w/ 3-color ePaper displays. I'm sure he has his ideas too.
-
Static discharges could be an issue... capacitors can help, worst case you have to add 'transient arrestors'... but from your setup I would expect that nothing ever can touch the blank wires of your thermistor.
Sinc you do not show any code, it is difficult to make some comments about why a puck would completely crach. I could think of some issue in setTimout() / setInterVal() usage that could lead to buffer overruns. But that is a wild guess...
-
Hi, skimmed over your code... noticed several things... some are coding conventions which do not break the code but make it more difficult to build a mind map - map the code in the mind for grasping. Beside that, I noticed your Polygon = [] and its population w/ values for drawing. I could not figure how many points you add, but you have to be aware of the limit it has. Your may have too many points. Not all all drawn which could explain the missing parts. To get thru a polygon with too many values, you have to break it up into multiples to compose the final one. See Swiss Federal Railway Clock modeled w/ Circular Gauges. It's less about the clock, it is about the circular gauges: I use some algorithm to compose a partial circle (arc) drawn using polygons by actually drawing multiple segments of that partial circle (arc)... (the full circle is just a partial circle / arc of 360 degrees).
Addendum: see g.drawPoly/fillPoly have a limit of 64 nodes - Your Color wheel.js uses 72 segments... which puts you already 12+% beyond the max limit. To achieve that: think about drawing two circles using Espruino's Graphics method .drawCircle(): draw the outer circle, and then clear the inner portion with another one... That way you take advantage of the best resolution with the highest speed.
-
@user156811,
before promises, I did non-blocking sequencing in a different way - see: