Skip to content

Instantly share code, notes, and snippets.

@fanoush
Last active October 16, 2020 13:09
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fanoush/ce461c73c299834bcb53a615721b5a2e to your computer and use it in GitHub Desktop.
Save fanoush/ce461c73c299834bcb53a615721b5a2e to your computer and use it in GitHub Desktop.
DS-D6 Espruino tests
Modules.addCached("DSD6OLED",function(){
//modified SSD1306, 128x32 but needs 0xda,0x12
// commands sent when initialising the display
var initCmds = new Uint8Array([
0xAe, // 0 disp off
0xD5, // 1 clk div
0x80, // 2 suggested ratio
0xA8, 31, // 3 set multiplex, height-1
0xD3,0x0, // 5 display offset
0x40, // 7 start line
0x8D, 0x14, // 8 charge pump
0x20,0x0, // 10 memory mode - horizontal
0xA1, // 12 seg remap 1
0xC0, // 13 comscandec
0xDA, 0x12, // 14 set compins, height==64 ? 0x12:0x02,
0x81, 0xCF, // 16 set contrast
0xD9, 0xF1, // 18 set precharge
0xDb, 0x40, // 20 set vcom detect
0xA4, // 22 display all on
0xA6, // 23 display normal (non-inverted)
0xAf // 24 disp on
]);
// commands sent when sending data to the display
var flipCmds = new Uint8Array([
0x21, // columns
0, 127, // OLED_WIDTH-1
0x22, // pages
0, 3 /* (height>>3)-1 */
]);
var rotCmds = Uint8Array([
0x20,0x0, // 10 memory mode - horizontal
0xA1, // 12 seg remap 1
0xC0, // 13 comscandec
]);
var rot;
var gfxV;
var gfxH;
exports.connectSPI = function(spi, dc, rst, callback, options) {
if (rst) rst.reset();
var cs = options?options.cs:undefined;
var r = options&&options.rotation?options.rotation:90;
if (options && options.contrast>=0) initCmds[17] = options.contrast;
var oled = {};
gfxV=Graphics.createArrayBuffer(32,128,1,{vertical_byte : false});
gfxH=Graphics.createArrayBuffer(128,32,1,{vertical_byte : true});
oled.isOn=false;
oled.init = function(cmdArray){
if (cs) cs.reset();
// configure the OLED
digitalWrite(dc,0); // command
spi.write(cmdArray);
digitalWrite(dc,1); // data
if (cs) cs.set();
};
oled.setRotation = function(r){
if (r=== 0){rotCmds[1]=1;rotCmds[2]=0xa1;rotCmds[3]=0xc8;}
if (r==180){rotCmds[1]=1;rotCmds[2]=0xa0;rotCmds[3]=0xc0;}
if (r== 90){rotCmds[1]=0;rotCmds[2]=0xa1;rotCmds[3]=0xc0;}
if (r==270){rotCmds[1]=0;rotCmds[2]=0xa0;rotCmds[3]=0xc8;}
oled.gfx=(r%180===0)?gfxV:gfxH;
rot=r;
oled.init(rotCmds);
};
if (rst) digitalPulse(rst,0,20);
setTimeout(function() {
oled.init(initCmds);
oled.setRotation(r);
oled.isOn=true;
// if there is a callback, call it now(ish)
if (callback !== undefined) setTimeout(callback, 10);
}, 50);
// write to the screen
oled.flip = function() {
// set how the data is to be sent (whole screen)
if (cs) cs.reset();
digitalWrite(dc,0);// command
spi.write(flipCmds);
digitalWrite(dc,1);// data
spi.write(((rot%180===0)?gfxV:gfxH).buffer);
if (cs) cs.set();
};
// set contrast, 0..255
oled.setContrast = function(c) {
if (cs) cs.reset();
spi.write(0x81,c,dc);
if (cs) cs.set();
};
// set off
oled.off = function() {
if (cs) cs.reset();
spi.write(0xAE,dc);
if (cs) cs.set();
oled.isOn=false;
};
// set on
oled.on = function() {
if (cs) cs.reset();
spi.write(0xAF,dc);
if (cs) cs.set();
oled.isOn=true;
};
// return graphics
return oled;
};
});
Modules.addCached("DSD6",function(){
// D3 pin is battery voltage
// D2 pin is analog charger voltage
// with known 5V input 5.0/analogRead(D2) gave me 6.61207596594
// feel free to recalibrate yourself
exports.battVoltage=function(){
var v=6.61207596594*analogRead(D3);
poke32(0x50000700+3*4,2); // disconnect pin for power saving, otherwise it draws 70uA more
return v;
};
exports.chargerVoltage=function(){
var v=6.61207596594*analogRead(D2);
poke32(0x50000700+2*4,2); // disconnect pin for power saving, otherwise it draws 70uA more
return v;
};
function vibon(vib){
if(vib.i>=1)D25.set();else analogWrite(D25,vib.i);
setTimeout(viboff,vib.on,vib);
}
function viboff(vib){
D25.reset();
if (vib.c>1){vib.c=vib.c-1;setTimeout(vibon,vib.off,vib);}
}
exports.vibrate=function(intensity,count,onms,offms){
vibon({i:intensity,c:count,on:onms,off:offms});
};
exports.initOLED=function(rot,f){
require("Font6x8").add(Graphics);
require("Font6x12").add(Graphics);
require("Font8x12").add(Graphics);
require("Font8x16").add(Graphics);
var spi=SPI1; //new SPI()
spi.setup({mosi:D6,sck:D5,baud:8000000});
if (f===undefined) f=function(){
o.gfx.setFont6x8();
o.gfx.drawString("Espruino on DS-D6",20,12);
o.flip();
};
if(rot===undefined) rot=270;
var o=require("DSD6OLED").connectSPI(spi,D28,D4,f,{cs:D29,rotation:rot});
exports.OLED=o;
};
var tOff=0; // offset to remember total runtime when changing clock
var sT=global.setTime;
//espruino IDE calls setTime so override it to keep track of change
global.setTime=function(t){
var c=getTime();
sT(t);
tOff+=getTime()-c;
};
//("2019-08-26T14:48:00",2)
exports.setClock = function(t, z) {
//var c=getTime();
if(z!==void(0))E.setTimeZone(z);
setTime(Date.parse(t)/1E3);
//tOff+=getTime()-c;
};
exports.getUptime = function() {
return getTime()-tOff;
};
/*
var KXREG = {
INS1:0x12,
INS2:0x13,
INS3:0x14,
STATUS_REG:0x15,
INT_REL:0x17,
CNTL1:0x18,
CNTL3:0x1a,
ODCNTL:0x1b,
INC1:0x1c,
INC2:0x1d,
INC4:0x1f,
TILT_TIMER:0x22,
WUFC:0x23,
ATH:0x30,
BUF_CNTL2:0x3b
};
exports.ACCREG=KXREG;
*/
function accRead(reg,len){i2c.writeTo(0x1f,reg);return i2c.readFrom(0x1f,len);}
function accWrite(reg,data){i2c.writeTo(0x1f,reg,data);}
//var i2c=new I2C()
var i2c=I2C1;
exports.initAccel=function(){
i2c.setup({scl:13, sda:14, bitrate:400000});
};
function accRegDump(reg){
val=accRead(reg,1)[0];return val.toString(10)+" 0x"+val.toString(16)+" %"+val.toString(2);
}
exports.accINSDump=function(){
console.log("INS1:",accRegDump(0x12),"INS2:",accRegDump(0x13),"INS3:",accRegDump(0x14));
};
exports.accelCoords=function(){
coords=new Int16Array(accRead(0x06,6).buffer);
return {x:coords[0],y:coords[1],z:coords[2]};
};
exports.accRead=accRead;
exports.accWrite=accWrite;
exports.accRegDump=accRegDump;
});
var w=require("DSD6");
w.initOLED(270); // init and set to landscape mode
var o=w.OLED;
function setupSerial(s){
if (!s) s=Serial1;
s.setup(38400,{rx:D22,tx:D23});
}
function resumeConsole(s){
setupSerial(s);
setTimeout(()=>{s.setConsole();},50);
}
function pauseConsole(s){
if (!s) s=Serial1;
if(s._options){
Bluetooth.setConsole(1);
setTimeout(()=>{
var rx=s._options.rx;
s.unsetup();
rx.mode("input_pulldown");
setWatch(()=>{resumeConsole(s);},rx,{edge:'rising',debounce:30});}
,500);
}
}
function getAdvertisingName(){
var adv=new Uint8Array(NRF.getAdvertisingData());
//aray of len,type,data records
//9=name, see https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile/
for (i=0;i<adv.length;i+=adv[i]+1){
if (adv[i+1]==9) return E.toString(new Uint8Array(adv.buffer,i+2,adv[i]-1));
}
return "";
}
var advertising=true; //by default
function setAdvertising(enable){
if (enable===undefined) return advertising;
if (enable) NRF.wake(); else NRF.sleep();
advertising=enable;
}
/*
// watch KX023 interrupt pin
setWatch(function(s){
if (s.state){w.accINSDump();console.log(s,w.accRegDump(0x17));}
},D15,true);
*/
//w.vibrate(0.75,8,500,600)
//setTClock("2019-01-06T10:35:02",2)
// show clock in landscape mode
var clockFace = {
offms: 6000,
show : function(o){
if (!this.run) return;
var g=o.gfx;
g.setFont6x8();g.clear();
var d=(Date()).toString().split(' ');
var dt=d[0]+" "+d[1]+" "+d[2]+" "+d[3];
g.drawString(dt,64-g.stringWidth(dt)/2,0);
g.drawString(this.v,0,24);
g.setFont8x16();
g.drawString(d[4],64-g.stringWidth(d[4])/2,9);
o.flip();o.on();
// schedule refresh on next second
this.tid=setTimeout(function(t,o){
t.tid=-1;
t.show(o);
},1000-Date().getMilliseconds(),this,o);
},
tid:-1,
run:false,
init: function(){
this.v=w.battVoltage().toString().substr(0,5)+"V";
this.run=true;
},
exit: function(o){
this.run=false;
if (this.tid>=0) clearTimeout(this.tid);
this.tid=-1;
return true;
},
off: function(o){
this.exit(o);
}
};
var infoFace = {
// from https://devzone.nordicsemi.com/f/nordic-q-a/1171/how-do-i-access-softdevice-version-string
sdver : {
"81":"2.0.0",
"88":"2.0.1",
"8c":"3.0.0",
"91":"3.1.0"
},
page: 0,
offms: 10000,
show: function(o){
var g=o.gfx;
g.setFont6x8();g.clear();
switch(this.page){
case 0:
var bv=w.battVoltage().toString().substr(0,5)+"V";
var chv=w.chargerVoltage().toString().substr(0,5)+"V";
g.drawString("MAC: "+NRF.getAddress().toUpperCase()+"\nUART: "+((Serial1._options)?"ON, "+Serial1._baudrate:"OFF")+"\nCharger: "+(w.chargerVoltage()>0.5 ? chv:"OFF")+"\nBattery: "+bv);
break;
case 1:
var e=process.env,m=process.memory();
g.drawString("Ver: "+e.VERSION+
" S132-"+this.sdver[peek16(0x300c).toString(16)]+
"\nName: "+getAdvertisingName()+ (advertising?"":" (off)")+
"\nConsole: "+e.CONSOLE+
"\nVars free:"+m.free+" used:"+m.usage);
break;
}
o.flip();o.on();
},
exit: function(o){
this.page++;
this.page%=2; //2 pages
if (this.page==0) return true;
this.show(o);
return false ; //allow switch to next face only after all pages are shown
},
init: function(){
this.page=0;
},
off: function(o){
// toggle advertising if screen goes off on page 1
if (this.page==1) {w.vibrate(1,1,50,0);setAdvertising(!advertising);}
}
};
var offid=-1;
var offms=5000;
var fcurr=-1;
var fprev=-1;
var faces = [
clockFace,
infoFace
];
function buttonHandler(s){
//var dbl=(s && s.lastTime && (s.time-s.lastTime)<0.5);
//if (dbl)console.log("double click");
var fshow=1;
if (fcurr<0){
// nothing active, make first one
fprev=fcurr;
fcurr=0;
if (faces[fcurr].init) faces[fcurr].init();
} else {
// ask active one to exit
if (!faces[fcurr].exit || faces[fcurr].exit(o)){
// ok exit from current face allowed
fprev=fcurr;
if(o.isOn) {
fcurr++; if (fcurr >= faces.length) fcurr=0;
} else fcurr=0;
if (faces[fcurr].init) faces[fcurr].init();
} else fshow=0;
}
if (offid>=0) clearTimeout(offid);
var foffms=faces[fcurr].offms;
offid=setTimeout((f)=>{
if (f>=0 && faces[f].off) faces[f].off(o);
o.off();offid=-1;fcurr=-1;
},(foffms>0)?foffms:offms,fcurr);
if (fshow) faces[fcurr].show(o);
}
setTimeout(()=>{
o.setContrast(10);
o.off();
setWatch(buttonHandler,BTN1,true);
},3000);
setupSerial();// first set to known state
// now pause serial console for power saving, it will be enabled when RX goes high
// it should be enough to connect to serial adapter
pauseConsole(Serial1);
@maxic62
Copy link

maxic62 commented Sep 5, 2019

Hello !!
thanks for sharing this.
I'm not able to run this code in my freshly flashed DS-D6

Espruino IDE tells me:
Module DSD6OLED not found - Module DSD6 not found
and the console:
>>> Loading modules loadModule(DSD6OLED) loadModule(DSD6) ERROR: getURL("https://www.espruino.com/modules/DSD6OLED.min.js") error : Not Found ERROR: getURL("https://www.espruino.com/modules/DSD6.min.js") error : Not Found ERROR: getURL("https://www.espruino.com/modules/DSD6OLED.js") error : Not Found WARNING: [notify_warn] Module DSD6OLED not found ERROR: getURL("https://www.espruino.com/modules/DSD6.js") error : Not Found WARNING: [notify_warn] Module DSD6 not found

Where to find those files ? What I missed ?

Mpow DS-D6
Flashed with D6 flasher (espruino_2v04_15_SDK11.zip)
Espruino IDE connected over BT

@fanoush
Copy link
Author

fanoush commented Sep 5, 2019

these should be just harmless warnings, I have them too, the module is added dynamically via Modules.addCached("DSD6....,. code so the files are not needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment