Espruino on P8 smartwatch - ST7789 display driver in Inline C

Posted on
of 3
/ 3
  • I think that would be worth investigating as I am not convinced that my current implementation is very robust. I assume the Bangle uses SW SPI as its the same NRF5x jshardware.c implementation. Is there any reason why you do not use HW SPI with DMA?

  • It was just that it felt like I couldn't do anything at the same time as the SPI transaction anyway, plus nRF52 max SPI was 8MHz so there didn't seem much in it - especially with the overhead as it's only generally transferring 16/32 bytes at a time IIRC.

    I'd be interested to see if there was an actual performance improvement though

  • What about battery? I was thinking one of reasons to use software bitbanging was that HW spi takes extra power on top of CPU which is already on? Also display needs DMA, would it make sense to use DMA based SPI for reading from flash too?

  • Having thought about it, I think the current implementation is probably the best you can do as for the reasons below, it is difficult/impossible to use double buffering. In addition, I think enabling and disabling the HW SPI is quite legitimate - it already happens to switch from DMA SPI to normal SPI to read single bytes. For some graphics screens, you have to do something similar to adjust to lower the bus speed for the touch controller if shares the display bus.

    Double Buffering

    My attempt at this - which works well when not using SPI flash - failed with a SPI timeout for - I think - the following reason. The driver starts a DMA operation to flush a buffer full of pixels and then returns to drawImage which accesses SPI flash to read the color palette. This read stops the DMA transfer with no completion interrupt so when it comes to try and flush the next buffer you get the SPI timeout.

    I do not think that there is a general solution- other than synchronous single buffering - to stopping the CPU accessing the SPI flash in the time available during the DMA transfer. I tried blocking the SPI flash read while the DMA is in operation but this causes a sort of deadlock - #drawImage cannot fill the next buffer because it is waiting for a spi flash read which cannot complete because it is waiting for the bus to be released.

    I have persevered with the driver as I would like to run different apps with different graphics requirements - you can see the result in the video below.

    @fanoush - Many thanks for your invaluable help with this - looking forward to softdevice+bootloader upgrade package to move to SDK12 as I need the secure connection to connect my phone.

  • looking forward to softdevice+bootloader upgrade package to move to SDK12

    it is over there, the upgrade was tested by @enaon and seems to be working, use the to upgrade to SDK12 and then get one of those prebuild SDK12 zips or build it yourself, I have put SDK12 board files there too

  • Many thanks, I assume, I flash the upgrade zip first and then I can flash normal Espruino builds as in BOARD=P8-SDK12 RELEASE=1 make ?

  • yes, or as in make -j BOARD=P8-SDK12 RELEASE=1 DFU_UPDATE_BUILD=1

  • A small update - I have now got double buffering to work with SPI flash. The solution is to introduce a simple spin lock which blocks any attempt to do a flash read until the DMA transfer has finished. I used the existing macro WAIT_UNTIL for the spin lock so that it can timeout if a DMA interrupt goes missing.

  • Interesting Pinetime effort­tid=14623

    Maybe Bangle can do it including sound via piezo speaker?

    The video is already converted here­pple/tree/master/src/bad_apple

    Also nice trick with SPI DMA there, the whole initial rectangle setup commands/data sequence of ST7789 is sent as single DMA transfer with just carefully timed DC pin toggling (via timer and PPI) while the DMA transfer runs­pple/blob/master/src/drivers/pinetime_di­splay_driver/display_fast.c#L123
    That could be used in current LCD_SPI_UNBUF driver to speed up small rectangles.

  • Nice, I like the style of Set, easy to handle, even for lefties.

  • Wow, that speed is impressive. I didn't think that was even really possible on 52832 with SPI. I guess they can run 12 bit, but even so...

    The timer + PPI for DC is really neat - I bet that would speed up things a lot!

  • Or another way to sound via the hardware just like MT17 bangle with ATS300X, based nrf52, can play music without smartphone

    1 Attachment

    • IMG_20210814_174317.jpg
  • hello @fanoush, I tried a build of espruino_2v21.9 on p8 and magic, and it seems the inline display driver gets broken. The watch boots, but displays only the last screen that was on before the firmware upgrade. Is there something I could maybe try?

    Actually I just wanted to try the jit feature, just to test if it could speed things up a bit, do you maybe know of a version of espruino with jit that your driver works?

  • try to replace E.toString by E.toFlatString, also new tokenisation of strings broke older InlineC compiler output, wrap atob() into E.toFlatString() too (in var bin=atob())

    new compiler now generates something like var bin=(E.toFlatString||E.toString)(atob(".­...."))
    EDIT: was wrong first time, toFlatString comes first, fixed
    EDIT2: it is actually || not |

  • and btw with 6.1 softdevices there is nasty bug with internal flash writing so use 6.0.0 or fix it in your source, see­ues/2000#issuecomment-1538847838
    this may actually be last thing to fix for 6.1.x S140 softdevices (the advertising bug is already fixed) so if you saw some improvement with 6.1.x it is worth fixing

  • super, thanks a lot, I am still on 6.0.0,because 6.1 was messing up the flash :)

    also, do you remember the version the compiler change happened? I just tried 2.17 and your driver works as it was.

    edit: I tried the inline driver with 2.21 and the changes you mentioned, but it outputs a "Compacting.." message on the ide when I am uploading, and after a while it disconnects, I think it softbricks, I do a reset using the watchdog to connect again.

    Maybe I did something wrong? I just replaced all E.toString with E.toFlatString, and used var bin=E.toFlatString(atob(".....")) ( I also used E.toString, same result)

  • update: it works :)

    I cannot send the file using the ide, it results in a soft brick, but the loader did it, thank you.

  • but the loader did it

    IDE and official loader now does pretokenisation of strings and also expands atob into binary string before upload for 2.21 firmware. which loader worked? maybe your older forked one which does not have this feature yet? or maybe you turned off pretokenisation in loader and have it enabled in ide?
    there also was a bug in ide/loader regarding this, so older cached version could break it too.

    if you preview the file in storage in IDE it can be seen whether atob was replaced or not.

  • yes I used the older forked loader, I can see the atob was not replaced. I see I have some catching up to do, for now magic3 with 2.21 and 6.1.1 seems to work fine, thanks again.

  • and 6.11 seems to work fine

    You mean S140 6.1.1? and you reduced writing block size to 2048?
    If you find any difference/bug with 6.1.1 please report it to issue­ues/2465, it looks like it might be good to upgrade to 6.1.x for proper long range/coded phy support.

  • You mean S140 6.1.1? and you reduced writing block size to 2048?

    I think so, it is the one you have on your github, and I think I managed to reduce the block size to 2048, I am not very sure I did it right though.

    It works, but I am facing some issues when connecting to my unicycle, I think I have seen the same problem in the past, I remeber that I was able to overcome it, but I need to remember how. I have the same problem with the bangleJS2 on 2.21, so it seems that it is not magic3 related, the bangle has very simmilar behaviour ( I am using 7.5ms connection interval) .

    The connection takes some more time, and it feels like there are two of them at the same time, one goes through and one fails, causing my script to restart comms, but it maybe be something else, I will play a bit more.

    also, I did loose the advertising of the magic(2.21 /6.1.1 -and I tested 6.1.0 too, the same as 6.1.1 as far as I can tell) two or three times, I am not sure what caused it, reset()/E.reboot() did not help, I had to use the watchdog to restart, and then it was visible again.

    I have a disable/enable BT switch on the gui, this does not work too, if I disable the BT it will not be visible once enabled, reset()/E.reboot() does not help, only the watchdog works for restoring incomming connections. (this also aplies to the banglejs2, so maybe it is espruino 2.21 related -Edit: disable/enable BT using the bangle os bluetooth connectable menu works, so maybe something has changed and the way I do it is not correct anymore.)

  • sory to spam on this thread, last one :)

    This is what I am getting (most of the times, some times it conects) on the bangle2 2.21 when trying to connect to a unicycle using my scripts.

    Uncaught Error: Unhandled promise rejection: Disconnected
    Uncaught InternalError: BLE task completed that wasn't scheduled (SERVICE/NONE)
    Uncaught Error: ERR 0x8 (INVALID_STATE) (:2082)

    is bangle using 6.1.x too?

  • is bangle using 6.1.x too?

    I don't think so. there is 6.0.0. when building full hex here­b/master/make/family/NRF52.make#L42
    unless you updated it there should be 6.0.0

    maybe some delay between connecting and reading data could help, I think there is MTU negotiation running right after device is connected, but it is there too also even for SDK12

  • maybe some delay between connecting and reading data could help, I think there is MTU negotiation running right after device is connected, but it is there too also even for SDK12

    thanks, I think I remember talking about this in the past, adding delays did help, it now allways connects, but only if the interval is 7.5-100, 7.5-7.5ms will not work on the bangle js2 for me, nothing like the p8 or the magic with 6.0.0. Strange, I will play more., thank you for your time.

    Edit: I just used 6.0.0 in the magic with 2.21, it behaves like the bangle, connects if delays are in place but not in 7.5 ms, comms are slow and it disconnects every 5 secs or so, strange, I think I remember that it was related with the feature of multiple connections that was introduced some time back, but I may have it mixed up in my mind.

  • OK, I'll dig up my Magic3 and try. BTW they are quite cheap on aliexpress now. Here­73233740.html it is for US$11.50 for me including VAT and free shipping. I couldn't resist (again) and got some more.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Espruino on P8 smartwatch - ST7789 display driver in Inline C

Posted by Avatar for fanoush @fanoush