-
The blink is because the Bangle 1 screen is not buffered so you are seeing the delay between the second hand being deleted and then redrawn. It is noticeable because in this face, the second hands overlap the numbers so they have to be redrawn on every tick. There is now a new version (in the same place) which reduces the delay by only redrawing the 4 numbers that are actually overlapped by the second hand. A better approach would be to be to use an image buffer but with 4 colours this would need about 200*200*2/8 = 10K bytes which should fit but would take most of free memory.
-
Thanks for the kind words. There is a version of the Braun face for the original Bangle:
The nice thing about the brAun logo is that the A is the middle letter and can be centred in the watch. bAngle would look asymmetric.
BTW: The Apple Notification app is now obsolete as Gordon has provided an IOS Integration app. It did work well with a fimware hack but was flaky without it:(
@Gordon - should I do a PR to remove the ANCS app? -
Oops - accidentally deleted the image in my previous post - now restored. I have added the Braun face to
multiclock
which you can load from here - in advance of submission to the offical BangleApps repository. -
I had a go at a Braun face this afternoon and the result is below. The problem with using grey is that it can only be achieved by dithering on the Bangle2 and as a result looks terrible on narrow marks -so the marks are white.
You can see the effect of dithering on the orange second hand which is a made up of red and green pixels - I think it looks better in solid red. -
-
The time to draw the dial on a Bangle2 (with radius 88 rather that 120) with the code above took 376ms. The time using a version of
drawRotRect
that does not usetransformVertices
was 490ms - or 114ms slower. Timed using:var tt = Date.now(); dial(); console.log("Time: "+Math.ceil(Date.now()-tt)+"ms");
-
It's said that the essence of good Software Engineering is reuse (plagiarism?) so in developing my own analog clock faces, I have been looking through the code of many of the clocks in the BangleApps repository. In trying to get clock faces to render as quickly as possible, I found that the use of the Espruino graphics operation
transformVertices
from the builtin Graphics class helped enormously. Using the Github search facility, I found only two apps using the operation in BangleApps - neither are Analog Clocks - hence I hope the following example may be of interest. The example uses the thetransformVertices
operation in implementing thedrawRotRect
function used in the Beeb Clock (reuse in action).The function places a rectangle rotated around the centre of the clock dial at a parameterised distance from the centre of the clock. I have used it for the following Bold Clock influenced face:
The following are the functions to draw the dial and the hands of this clock.
var cx = g.getWidth()/2; var cy = g.getHeight()/2 Graphics.prototype.drawRotRect = function(w, r1, r2, angle) { var w2=w/2, h=r2-r1, theta=angle*Math.PI/180; return this.fillPoly(this.transformVertices([-w2,0,-w2,-h,w2,-h,w2,0], {x:cx+r1*Math.sin(theta),y:cy-r1*Math.cos(theta),rotate:theta})); } function dial() { for (let a=0;a<360;a+=6) if (a % 90 == 0) g.setColor(g.theme.fg).drawRotRect(8,105,120,a); else if (a % 30 == 0) g.setColor(g.theme.fg).drawRotRect(4,105,120,a); else g.setColor(0.6,0.6,0.6).drawRotRect(2,110,120,a); } let hourHand = g.drawRotRect.bind(g,6,6,66); let minuteHand = g.drawRotRect.bind(g,3,6,100); let secondhand = g.drawRotRect.bind(g,2,3,100);
This example uses a rectangle, however, the approach can just as easily be applied to polygons representing more complex hands.
-
The red hand on the watch faces in the pictures are second hands which the NRF52832 handles fine with barely noticeable flicker. The problem with faster than one second is that the flicker caused by unbuffered update becomes very obvious which is why you need buffering. I tried it on the ROCK and because it has the double buffered
lcd_spi_unbuf
and the faster 32MHz SPI it can manage about 150ms for a complete screen rewrite of 240x280 pixels. -
I simply invoke
process.memory()
from the Web IDE console to get the current memory usage. The SN80 has about 2500 espruino memory variables in total - the change to the LCD driver frees up about 300. In general, real delays are a bad idea in Espruino, however, Timeout delays let other bits of code run which cause problems at system initialisation which is why I am using the real delays which stop anything else running while the LCD driver initialises the screen.A sweeping second hand would need to update the screen every 166ms and use a screen buffer as you say to avoid excessive flicker. I tried it as an experiment using a full screen 2 bit image buffer and it took 300ms for each update. It might work with @fanoush 's buffered driver....
-
More traditional watch faces look great on the SN80. Here are some new ones.
The first is based on @HughB 's Bold clock face. In general, the dial for these faces take some time to display and the watch looks terrible if you have to redraw the dial each time the hands move or the LCD turns on. The trick is to ensure that the hands do not overlap the dial markings and consequently as long as the screen is never completely cleared, you can leave the dial undisturbed in the LCD display memory so that it is instantly displayed on power on etc.@yngv126399 I started on the SN80 using a version of your LCD driver and I noticed that it uses a lot of memory. I think the problem is that the memory used for the initialisation data
ST7789_INIT_CODE
is not released. I have programmed it as separate commands but you could just move the declaration intodispinit
which should also work. In addition, my current version of the driver in the WatchApps repository uses real delays rather than timeouts. This reduces start up glitches and means you do not need the 500ms timeout delay at the start of apps. -
-
@yngv126399 I got hold of an SN80 recently to play with circular displays and I have now fixed the lcd_spi_unbuf driver. The problem was that for some reason, no pixels are displayed if the address window you set up is not completely filled. This means that double buffering does not work, so I have fixed the problem for single buffering - just remove the -DLCD_SPI_DOUBLEBUF=1 declaration in the board file. I have left a firmware build with the revised driver here . I have got most of the P8 bangle emulation environment to run on the SN80 including accelerometer, touch screen and heart rate sensor- see picture below.
.
I have made the widgets moveable, so you can specify the location of the widget panel. The clock face above moves the panel top or bottom to minimse it being obscure by the hour hand.
The only remaining problem is the physical button which should be on D13 or D17, however, I have tried these and other unallocated pins with no success. I would be interested to know if you have got the button to work as I suspect that I may have a hardware fault. I am currently using long touch to replace the button - which works OK.
-
-
-
The advantage of using the Bangle is that the firmware in
jswrap_bangle.c
andnmea.c
turns the NMEA strings received from the GPS device into espruino events. To implement the server on the B5 you would need to have an NMEA parser etc - probably too slow in Javascript so it would probably need firmware hacking - although all the software is already there for the Bangle 2. A further advantage is that the Bangle has a relatively large 350maH battery. Advantage would be that the B5 is smaller to carry around:) -
Bangle GPS service for Kospet ROCK and Magic 3
In a previous post I posted the image of a Bangle simulation environment for the ROCK and Magic3 watches. These watches have an NRF52840 processor and a large 240x280 screen which in the case of the ROCK is very bright.
The image showed Wave Clock loaded directly from the BangleApp Loader as a demonstration of the Bangle emulation environment for the ROCK. However, this is very limited as many of the most interesting Bangle Apps use sensors such as GPS so following an idea suggested some time ago by @fanoush, I have implemented an App for the Bangle which provides a BLE service that makes the Bangle's GPS readings available externally.
Using this, the ROCK and Magic 3 can now run Bangle GPS apps loaded again directly from the App Loader. The Open Street Map App is shown below:
The interface to the GPS on the Bangle 1 & 2 is very narrow and that facilitates emulation. For interest, I include the full emulation code here:
Bangle.setGPSPower = function(on){ if (Bangle.gpsOn && on) return; //already started function unpack(v){ var fix = v.getInt8(29); function ck(d) {return d==-1 ? NaN : d;} return { lat:ck(v.getFloat32(0)), lon:ck(v.getFloat32(4)), alt:ck(v.getFloat32(8)), speed:ck(v.getFloat32(12)), course:ck(v.getFloat32(16)), time:new Date(v.getFloat64(20)), satellites:v.getInt8(28), fix:fix, hdop:ck(v.getFloat32(30)), } } if (on) { Bangle.gpsOn=true; NRF.requestDevice({timeout:4000, filters: [{ name: 'gps' }] }).then(function(device) { //console.log("Found"); return device.gatt.connect(); }).then(function(g) { //console.log("Connected"); Bangle.gpsgatt = g; return g.getPrimaryService("974e0001-1b9a-4468-a83d-7f811b3dbaff"); }).then(function(service) { return service.getCharacteristic("974e0002-1b9a-4468-a83d-7f811b3dbaff"); }).then(function (c) { Bangle.gpscharistic=c; //console.log("Got Characteristic"); Bangle.gpsInterval = setInterval(function(){ Bangle.gpscharistic.readValue().then(function(d){ Bangle.gpsFix=unpack(d); Bangle.emit("GPS",Bangle.gpsFix); }); },1000); }).catch(function(e){ E.showMessage("GPS: "+e,"ERROR"); }); } else { Bangle.gpsOn=false; if (Bangle.gpsInterval) Bangle.gpsInterval = clearInterval(Bangle.gpsInterval); if(Bangle.gpsgatt) Bangle.gpsgatt.disconnect(); delete Bangle.gpsgatt; delete Bangle.gpscharistic; } } Bangle.getGPSFix = function() {return Bangle.gpsFix;}
The Bangle GPS server code can be found here.
I have found the Bangle 1 GPS to be more sensitive than the Bangle 2, so it may be that if you have both Bangles, this may be of use. I have found the Bluetooth link between ROCK and Bangle really reliable and its no problem to carry the Bangle in a top pocket or a back pack.
-
I have now finished an initial version of a Bangle compatible environment for the ROCK and Magic3 watches. You can find it in this repository. The firmware uses a double buffered version of
lcd-spi-ubuf.c
which combined with 32Mhz SPI gives much faster screen update than was possible on the P8. The Bangle emulation is implemented in Javascript so is easy to update. Emulation functions are loaded into the NRF52840 internal flash for better performance. They allow you to load apps directly from the Bangle App Loader if you ignore the warnings, however, since the ROCK and Magic3 have very few sensors it is really only Clock apps that are truly portable. As an example, the Wave Clock which runs on both Bangle and Bangle 2 is shown below running on the ROCK - it was loaded straight from the official Bangle App Loader:The emulation has versions of setUI options so menus and prompts work.
-
-
I have also been getting a lot of these FIFO_FULL errors from a build of the latest version of Espruino for an NRF52840 - although it is for a Magic 3 watch. It seems to happen for me after interrupt generated events although I have also got it when loading a large amount of code from the editor window of the IDE into RAM.
-
Yes, but I am afraid that I did not follow the Bangle conventions exactly so my apps did require tweaks. I agree with your views on jswrap_bangle.c but I think the new touch and layout stuff is worth getting to work on the P8.
BTW does the Kospet Rock have a touch screen? It looks like it has three buttons.
-
Actually, for the P8, I did not use jswrap_ bangle.c as I found it easier to develop drivers in Espruino. I intended to put these into C afterwards but the Espruino driver performance seemed quite useable so I did not bother. I plan to look at using the new Layout and touch UI stuff in the coming weeks as it should then be possible to run standard Bangle apps on the P8.
-
Hi, no plans to merge at the moment as I also had to add non-standard Espruino fns to disable and enable SPI to switch between lcd driver and storage access. Gordon rightly thinks this is a bit of a hack. It is unique to the P8 as in shares SPI. I will update the build to current Espruino in the next few weeks when I get a chance.
-
It may be that you have a version of the P8 with a different accelerometer.
accel.js
only works with the SC7A20 while your P8 may have a BMA421. Search here for more information. -
There is a very neat online build facility for NodeMCU for the ESP8266 https://nodemcu-build.com/ which lets users select the modules they want and it then builds a custom firmware. Something like that for Espruino might be a solution - but a lot of implementation effort:-(
This does seem to be the problem I referred to earlier. I did a quick spreadsheet to compute
(magnitude-8192)/32
which the step count algorithm does initially. Most values exceed 14 theRAW_THRESHOLD
( the average is 15.56). The step count algorithm assumes that at rest the magnitude will be 1g = 8192 which it will not be in all orientations for all accelerometers unless they are calibrated.