Skip to content

Instantly share code, notes, and snippets.

@fanoush
Last active January 1, 2020 18:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fanoush/56db50bd2392abedc15039bc6e7e5f06 to your computer and use it in GitHub Desktop.
Save fanoush/56db50bd2392abedc15039bc6e7e5f06 to your computer and use it in GitHub Desktop.
//manual watchdog pinging mode is dangerous for Espruino Web IDE upload with 'reset() before upload' enabled
//you can brick your device with partial upload caused by watchdog reboot in the middle of upload
//E.enableWatchdog(6, false);
//var wdint=setInterval(function(){if(!BTN1.read())E.kickWatchdog();},1000);
var log=console.log;
Modules.addCached("HX03WLCD",function(){
// commands sent when initialising the display
var initCmds = new Uint8Array([
0xAE, // 0 disp off
0xD5, // 1 clk div
0x51, //0x50, // 2 suggested ratio
0xA8, 63, // 3 set multiplex
0xD3,0x60, //0x0, // 5 display offset
0x20, //??? //0x40, // 7 start line
0xAD,0x81, //0x8B, // 8 enable charge pump
0xa0, //0xA1, // 10 seg remap 1, pin header at the top
0xc0, //0xC8, // 11 comscandec, pin header at the top
0xDA,0x12, // 12 set compins
0x81,0x80, // 14 set contrast
0xD9,0x22, // 16 set precharge
0xDB,0x35, // 18 set vcom detect
0xa4,
0xA6, // 20 display normal (non-inverted)
0x00, 0x10, 0xb0,
0xAF // 21 disp on
]);
/* bootloader OLED init
GPIO_CfgPinOutput(5);
GPIO_CfgPinOutput(6);
GPIO_CfgPinOutput(0x1d);
GPIO_CfgPinOutput(0x10);
*GPIO_OUTCLR = 0x10000; // D16 low
GPIO_ConfOutput4_28();
D4_PulseZero50ms();
SPILCD_SendCMD(0xae);
SPILCD_SendCMD(0);
SPILCD_SendCMD(0x10);
SPILCD_SendCMD(0xb0);
SPILCD_SendCMD(0x81); SPILCD_SendCMD(0x14);
SPILCD_SendCMD(0x20); // ????
SPILCD_SendCMD(0xa0);
SPILCD_SendCMD(0xc0);
SPILCD_SendCMD(0xa4);
SPILCD_SendCMD(0xa6);
SPILCD_SendCMD(0xa8); SPILCD_SendCMD(0x3f);
SPILCD_SendCMD(0xd3); SPILCD_SendCMD(0x60);
SPILCD_SendCMD(0xd5); SPILCD_SendCMD(0x51);
SPILCD_SendCMD(0xd9); SPILCD_SendCMD(0x22);
SPILCD_SendCMD(0xdb); SPILCD_SendCMD(0x35);
SPILCD_SendCMD(0xad); SPILCD_SendCMD(0x81);
SPILCD_SendCMD(0xaf);
*/
exports.connectSPI = function(spi, dc, rst, callback, options) {
var cs = options?options.cs:undefined;
var W=options&&options.width?options.width:128;
var H=options&&options.height?options.height:64;
initCmds[4] = H-1;
initCmds[13] = H==64 ? 0x12 : 0x02;
if (options && options.contrast) {
initCmds[15] = options.contrast;
}
if (rst) rst.reset();
var oled = Graphics.createArrayBuffer(H,W,1,{vertical_byte:true});
if (rst) digitalPulse(rst,0,30);
setTimeout(function() {
// configure the OLED
D16.reset(); // HX03W oled power?
if (cs) digitalWrite(cs,0);
digitalWrite(dc,0); // command
spi.write(initCmds);
digitalWrite(dc,1); // data
if (cs) digitalWrite(cs,1);
// if there is a callback, call it now(ish)
if (callback !== undefined) setTimeout(callback, 10);
}, 50);
oled.isOn=true;
// write to the screen
oled.flip = function() {
// 16 pages x 64 bytes
var page = 0xB0;
if (cs) digitalWrite(cs,0);
for (var i=0;page<0xC0;i+=H) {
digitalWrite(dc,0); // command
spi.write([page, 0x0, 0x10]);
page++;
digitalWrite(dc,1);// data
spi.write(new Uint8Array(this.buffer,i,H));
}
if (cs) digitalWrite(cs,1);
};
// 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();
poke32(0x50000700+4*16,2); // disconnect pin 16
oled.isOn=false;
};
// set on
oled.on = function() {
D16.reset(); // pin 16 output low - power for oled
if (cs) cs.reset();
spi.write(0xAF,dc);
if (cs) cs.set();
oled.isOn=true;
};
// return graphics
return oled;
};
});
Modules.addCached("HX03W",function(){
function pinOff(pin){
if (pin>=0&&pin<32) poke32(0x50000700+4*pin,2);
}
exports.battVoltage=function(){
var v=6.61207596594*analogRead(D3);pinOff(3);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("Font4x4").add(Graphics);
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.setRotation(1,0);
o.clear();
o.setFont8x12();
o.drawString("Espruino on HX03W",20,24);
o.flip();
};
var o=require("HX03WLCD").connectSPI(spi,D28,D4,f,{cs:D29});
exports.OLED=o;
};
var tOff=0;
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 i2c=new I2C()
var i2c=I2C1;
exports.initAccel=function(){
i2c.setup({scl:13, sda:14, bitrate:400000});
};
function accRead(reg,len){i2c.writeTo(0x1f,reg);return i2c.readFrom(0x1f,len);}
function accWrite(reg,data){i2c.writeTo(0x1f,reg,data);}
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("HX03W");
w.initOLED(270);
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(()=>{
rx=s._options.rx;
s.unsetup();
rx.mode("input_pulldown");
setWatch(()=>{resumeConsole(s);},rx,{edge:'rising',debounce:30});}
,500);
}
}
// show clock in landscape mode
var clockFace = {
show : function(o){
log("clockFace:show");
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);
var v=w.battVoltage().toString().substr(0,5)+"V";
g.drawString(v,0,48);
g.setFont8x16();
g.drawString(d[4],64-g.stringWidth(d[4])/2,9);
o.flip();o.on();
},
exit: function(o){
log("clockFace:exit");
return true;
}
};
var termFace = {
vars: {term: 0,
buffer: 0,
tid:0},
message: "Hello world\nThis is a test ",
show: function(o){
log("termFace:show");
var v=this.vars;
var g=o;
if (!v.term){
v.term = require("VT100").connect(g, {
charWidth : 4,
charHeight : 4
});
}
for (var i in this.message) v.term.char(this.message[i]);
o.flip();o.on();
},
exit: function(o){
log("termFace:exit");
var v=this.vars;
if (v.tid) clearInterval(v.tid);
v.tid=0;
if (v.buffer) v.buffer.set(o.buffer,0);
return true;
},
init: function(o){
log("termFace:init");
var v=this.vars;
if (!v.buffer)
v.buffer=new Uint8Array(128*64/8);
var b=new Uint8Array(o.buffer);
b.set(v.buffer,0);
o.setFont4x4();
if (!v.tid) v.tid=setInterval(()=>{this.show(o);},1000);
},
timeout: 7000
};
var happyFace = {
exitcnt: 0,
show: function(o){
if (this.exitcnt<3) return;
var g=o;
g.setFont8x12();g.clear();
g.drawString("Happy face :-)",10,16);
o.flip();o.on();
},
exit: function(o){
var g=o.gfx;
g.clear();
g.drawString("Exit countdown "+this.exitcnt,10,16);
o.flip();
return 0 >= this.exitcnt--;
},
init: function(){
this.exitcnt=3;
}
};
var offid=-1;
var offms=5000;
var fcurr=-1;
var fprev=-1;
var faces = [
clockFace,
termFace
];
function buttonHandler(s){
log("buttonHandler");
//var dbl=(s && s.lastTime && (s.time-s.lastTime)<0.5);
//if (dbl)console.log("double click");
if (fcurr<0){
// nothing active, make first one
fprev=fcurr;
fcurr=0;
if (faces[fcurr].init) faces[fcurr].init(o);
} else {
// ask active one to exit
if (!faces[fcurr].exit || faces[fcurr].exit(o)){
log("buttonHandler:exit from "+fcurr+"ok");
// ok exit from current face allowed
fprev=fcurr;
if(o.isOn) {
// if display is on switch to next, otherwise swith to first
fcurr++; if (fcurr >= faces.length) fcurr=0;
} else fcurr=0;
if (faces[fcurr].init) faces[fcurr].init(o);
}
}
if (offid>=0) clearTimeout(offid);
var t=(faces[fcurr].timeout)?faces[fcurr].timeout:offms;
if (t>0) offid=setTimeout((f)=>{
log("timeout "+fcurr);
if(f>=0 && faces[f].exit) faces[f].exit(o);
o.off();offid=-1;fcurr=-1;
},offms,fcurr);
faces[fcurr].show(o);
}
setTimeout(function(){
//o.setContrast(10);
o.off();
setWatch(buttonHandler,BTN1,true);
},3000);
setupSerial();
// pause serial console for power saving, it will be enabled when RX goes high, it should be enough to connect to serial adapter
pauseConsole();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment