-
• #2
I've just taken a look at the datasheet, and it looks like you'll have trouble using SPI. You need 4 data lines to change at the same time, so about your only choice is bit-banged IO.
As of the very latest version 1v72, Espruino can run code in an interrupt, as long as it's written using the inline assembler, so it would be possible to get a very steady high-speed update out of it - as well as using WiFi and drawing graphics.
I could provide some example code for that if needed. I have a side-project that would allow you to 'compile' JS code and run that in an interrupt, but that is probably still too far off being useful at the moment.
Having said all that, it is a bit of a faff. And while you could get the update speed high enough, the animations would still pause a little when you did an HTTP request.
You might find that you can get good enough using node.js with the WiringPi wrapper on a Raspberry Pi. If you can get the updates smooth enough then the multi-tasking on it would really help you out.
-
• #3
Yup 4 lines which are 2 clocks and 2 data out lines which 2 SPI interfaces would cover? Can I not use the 2 SPI interfaces on this board at the same time?
I have used hardware SPI to clock out dot matrix data in the past it works well :)
I looked at Raspberry Pi But they only have 1 SPI I really need 2.
I have no problem writing the core display update code in asm as long as its interrupt driven.
Edit:
I miss read the datasheet your right it is 1 clock and 4 actual data lines 2 colours but on 2 rows! Ah crap.I can offload the display update work to this board
http://www.embeddedadventures.com/led_matrix_display_driver_plt-2001.htmlI am hoping the i2c interface is supported on it though as I don't think uart will be quick enough to send all the pixel data. This is also open source so I can edit it to support i2c if not supported (They have a i2c header)
-
• #4
@russdx, doing things directly - without intermediate or sub controller - in javascript can become quite demanding... not just from a processing/cycle point of view, but also from a memory consumption point of view.
The combination of driving a decent sized display and driving it over SPI pushes the envelope. As @Gordon points out, there is always the option to become a sub and dive into assembler for selected operations. Even with a SPI driven sub controller - such as IL9341 controlling a 320x240px color LCD - updating the LCD becomes a challenge when Espruino has also to do some processing at the same time. For example, receiving GPS sentences, parsing them, and updating the display required me to go for optimizations, such as partial and staggered/skewed updates, in order to keep up with the 1Hz GPS data rate... most of the time :(. For code and video clip see uBlox GPS and 320x240 TFT LCD w/ touch screen post. There is though hope for you: In my case, Espruino does A LOT of processing - even heavy graphical processing: it generates the font... You may also look at my other posts related to driving the LCD.
Your suggestion to go with the PLT-2001v1 - which notably is a dedicated processor AND runs already at 100MHz (vs. 72Mhz) - looks to me the way to go.
This is not at all to put down Espruino, but specific bit banging and memory buffering tasks is - imho - not what Espruino as a board and as a language/SW environment is targeting. What it though does in combination with sub controllers handling those tasks, is the quick and easy programming the overall control job. Passing on/thru of larger data amounts though has to happen in streaming mode. Receiving an update of a 192x32x3 bit 'image' is close to 2.5KB and quite a lot for a store-and-forward. Im sure you have control over how your updating server can deliver the 'image' data and you could break it up in chunks. PLT-2001v1 would have to have at least a 2-page buffer capability to have not garbled display while the update is underway.
Alternative for temporary storage I use a F-RAM / Fe-RAM / M-RAM technology, which has the advantage of no wait cycles over the use of SD cards.
-
• #5
@allObjects in your case the slowness was from driving a 320x240x16 bit display. This is only 192x32x2 bit so the amount of data is far, far lower.
The controller board might be a good plan though - as it seems it'll handle multiple panels it might take a lot of the pain out of the updates.
How exactly did you plan on doing your 24fps animation? Is it:
- Streaming data directly off the server
- Grab data off the server, and then animate it on the microcontroller
I guess the first one could be a bit tricky, but second should be fine to do. Having said that, if you've got a controller board then you could just use a Pi - there would be more setup in terms of fiddling with the OS, but a bit less wiring as network is effectively built in.
- Streaming data directly off the server
-
• #6
Basically I have written this live train departure board in js using the canvas.
http://54.148.129.10/index.html?orig=RDG&dest=BPWI want to know display this data on a real dot matrix (the ones i linked to)
I think I will get that little driver board as it will save me time and pain :DI was under the impression espruino would be able to basically run this code standalone but instead of seeing it on a html page i will just copy the canvas pixel and convert to byte array and send them to the dot matrix driver board. (when animating it runs at around 24fps and the scroll is 12fps)
Once done it should not be connected to a pc. It should run 100% standalone and get its data using wireless and then send the data to the dot matrix driver board.
I wrote this project is js because i like using the canvas for graphical projects its easy to set pixels and so on. Maybe i should of just wrote it in .c and made a byte canvas and but then I would need to implement all the (comes for free with js) canvas methods like drawing and buffers and so on.
Also there is no font rendering going on that font is a custom (exact map of network rail font) but stored as my own format and i decode and draw it my self. Its not using canvas text.
Another quick question :)
Can we mix .c code and javascript? I know from above conversation calling asm is possible but can i write half this project in .c and have that running on the stm and then make calls to this from the javascript? -
• #7
The train time page looks really neat... Is it actually for someone, or is it just a personal project?
Yes, Espruino could do the animation just fine and push the pixels - but the graphics library doesn't have the same API as Canvas (on quite a constrained device, the whole stroke/fill stuff doesn't really make that much sense).
There's support for custom fonts - see here. You'd just have to put your font into the required format, which shouldn't take long at all. Then it's just a matter of using
g.drawString
andg.stringWidth
, so it should be nice and easy.The only thing I'd say is to queue the HTTP request after the 'train stops at' has gone offscreen. That way if there's a delay it won't be visible to the user (unfortunately when looking up a domain name, Espruino usually has to block while it's resolved).
If you want to use C, the easiest way is to just get Espruino's source code and then add your own source file, which can provide objects + functions that JavaScript can then use. You can compile C code on your PC and then dynamically load the compiled code into memory and register it as a function using
E.nativeCall
, but I haven't come up with any scripts to do that, so it's not going to be much fun.I doubt you'd need to do any of that though. Worst case is you have to do some fiddling around with the data from the graphics library to get it into a format that'll work with your display, but I think that'd be pretty easy to do quickly.
-
• #8
Just a personal project using the network rail LDB api. I take the train from bristol to reading every day for work so its nice just to see what the next trains I can take are / delays / cancellations etc..
My canvas only uses fillRect (just to draw a 1x1 pixel and drawImage (to copy different canvas's around) Is all this supported?
I think I will use that dot matrix driver board to drive the displays as all the code has been written and I can just plug the displays directly into it. Will save me a lot of time and effort hehe. (so will not need to write any dot matrix driver stuff my self hehe)
I read in another thread of yours we can run espruino on a rasp pi? I have one of the new A Plus models so was thinking run my little app on that and have it talking i2c to the dot matrix driver board. This way the rasp pi can take care of the networking and js canvas side and the dot matrix can take care of the display updates.
-
• #9
Yes, that should work - those are more or less the same, although drawImage may not be able to take 'graphics' as an argument. See http://www.espruino.com/Graphics for some examples. I'd really suggest you use the built-in custom font stuff though - it'll make your life so much easier.
I'm not sure anyone's written any interface code to link the driver board to Espruino, but it should be pretty simple to do.
Espruino can run on the Pi, yes - although there's no I2C support in it yet. I have to focus on the Espruino board which people actually pay me for, so I'm kind of reliant on others to contribute code for other boards - and there are only a handful of people that do unfortunately.
There is serial port support though, which in many ways is better as it's totally asynchronous.
There's also node.js on the Pi - although I'm not sure what the situation with the Canvas is - I guess there must be something.
-
• #10
Yeah I see what your are saying, I am trying to keep the code this way so I can still run the js in a normal browser and have it work as is.
I might have a look at writing the i2c Rasp Pi stuff because I will need to use this. I don't think i will be able to send all the frame data at 24fps over serial?
I have looked at node.js and there are a few canvas modules I can use.
I might look at rewriting it not to use the 'canvas' at all for the internal animations and just use my own byte array to store the pixel data. Then just have a switch for if its run in browser mode or on device. When on deivce it just sends the byte canvas directly to the dot matrix driver (in correct format) or if running in browser just draw my byte canvas onto a js canvas.
I will see what I get away with before I make this move hehe.
-
• #11
The dot matrix board serial is 115,200bps
If my math is correct this is far to slow for me to run 24fps :(
192x32x2 = 12288 bits
/ 8 = 1536 bytes (one frame, 3 colours)- 24 = 36864 bytes per second is the transfer rate I need to update this display.
This is why I will need to use its i2c interface (hopefully been written or I will be downloading the pic dev tools as well hehe)
- 24 = 36864 bytes per second is the transfer rate I need to update this display.
-
• #12
Yes, 115kbps does seem a bit slow for a nice animation.
However on the datasheet for the controller I see no mention of I2c (apart from a note saying it might be added later). By far the easiest thing to do would be to just increase the serial baud rate to 2M baud and then you're sorted.
However now I'm on the datasheet I don't see a way to send raw bitmap data to the controller either - so you may be out of luck there too.
It might be better to just use WiringPi on node.js on the Raspberry Pi to bit-bash the data directly to the LEDs (without the controller). It's worth a try - it may just work without being too glitchy.
Otherwise you could try a similar thing with the Espruino board - the more I look at the Embedded adventures one the less convinced I am.
-
• #13
It comes with full source code. So at the very worst I will just add in the i2c part my self. Or maybe up the uart? How fast can PIC uart hardware go? Like you said would also need to add some way of sending raw pixel data as well. So Cant really use this project out the box but I think it will still save me a lot of work even if I just wrote the firmware from scratch!
Unless I can get the dot matrix driver code hardware timer interrupt driven on Pi or Espruino it will be jumpy I think.
Maybe writing a small c class that runs the dot matrix display with hardware timers on the Espruino might be the way forward? and send it the frame data from the javascript
This was one of my other projects
http://www.pindmd.com/default.phpIt used very similar hardware to yours the STMF4 which is a powerful arm chip and when running the display just off software delays with the usb running as well the display was jumpy. I had to put the display update in a hardware timer driven routine to force it having priority and this solved the problem. Hopefully would be the same with the Espruino.
Least I got a few routes to go down :)
Basically a mixture of using Rasp Pi by its self or with the DMD controller board.
or Espruino by its self or with the DMD controller board. -
• #14
Reading the PIC32MX450F128H datasheet (quite a nice little microcontroller actually hehe)
http://ww1.microchip.com/downloads/en/DeviceDoc/60001185C.pdfSays
• Baud rates ranging from 76 bps to 25 Mbps at 100 MHzHopefully I can just bump the UART to a faster speed and use this. How fast can I send data using the Espruino UART?
-
• #15
Yes, bumping the UART seems easier. The STM32 will do at least 4mbps I think. Hopefully more than enough for the controller.
Just to add, if you're using Espruino the speed of JS execution isn't anywhere near as good as C. Using the built-in font code is likely to be 100x faster than writing your own.
If you wanted the code to work the same it'd be pretty easy to just write something like:
if (!g.drawString) { g.drawString = function(text,x,y) { // your original code in here }; }
Love the pinball display by the way - very cool.
Doing everything in Espruino with hardware IRQs is definitely an option though. I'd be interested in helping out however I can - it'd be a huge help to be able to do that kind of real-time scanning, if only for all the charlieplexed stuff that's out there now.
-
• #16
Trying to think of easiest way to convert my current text method I current have these params
function drawText(str,ctx,font,colour,x,y,width,align,spacing,debug)
Do you support align?
As long as the javascript can run my canvas at 24fps thats all I need :)
-
• #17
Edit: added my textManager
2 Attachments
-
• #18
There's no align built in, but it's easy enough to use stringWidth and then do what you want with it. I usually do something like:
g.drawString(text, x-(g.stringWidth(text)*(1-align)/2), y); // align -1 = right edge // 0 = center // 1 = left edge
Otherwise it looks like you can just replace your code under
// draw text
with it. -
• #19
Perfect :) I will convert that over.
And all this sort of code will run quite happily?
function createDepartureBoard(){ var c = document.getElementById("canvas"); c.width = 192*2; c.height= 32*2; boardCtx2D = c.getContext("2d"); boardBuffer = document.createElement('Canvas'); boardBuffer.width = 192; boardBuffer.height = 64; boardBufCtx2D = boardBuffer.getContext('2d'); msgBuffer = document.createElement('Canvas'); msgBuffer.width = 2000; msgBuffer.height = 32; msgBufCtx2D = msgBuffer.getContext('2d'); }
boardBufCtx2D.drawImage(msgBuffer,msgXPos,0,192,9,0,msgYPos+1,192,9);
-
• #20
This is not gona work... :(... Espruino is a server like context... window and document (global variables) are undefined, as are all the other view oriented browser global variables... With Espurino it's more like a node.js or Rhino environment... If you want your code to work unchanged, you have to come up with the emulation of these things. --- And like your idea to have it run anywhere... (I did the same for some stuff: developed in the browser emulating Espruino context, and then move it over...).
There is no html / view DOM, and therefore all these functions are not there. I did not look in detail into all of your code, but I think it is feasible.
I'll sit down and will give you some pointers... until then, have fun with Espruino.
-
• #21
Hey allObjects
Yes I have just figured this out my self hehe, I wrote this in javascript thinking I could directly port it onto a micro because I had heard of them running javascript I should of done a bit more research hehe.
My current plan is to rewrite all canvas code (I only use drawImage and fillRect) my self as byte arrays (very similar to Gordans graphics libary)
I will slightly adjust my textManager to draw the font to the byte array canvas and instead of using drawImage (I was only use this as a canvas copy) I will create a canvasCopy method to copy chunks of one byte canvas to another.
canvasCopy(orig,x,y,w,h,dest,x,y,h,w);
This way I will now not be reliant on any canvas object and could very easily port this to plain .c if I needed to.
My plan for the byte canvas (based on my pinDMD project) as I only need 3 colours I can get away with just (192*32*2)/8 = 1532 bytes canvas array which will save on memory. But then again creating a canvas which support 255 colours (192*32)*8 = 49151 bytes is bit larger and would be better in-case i want to use more colours?
I would convert this larger canvas byte array down to the compressed 4 colour version when sending data over i2c to the dmd controller :)
I would also need to swap out the way my code makes http requests with the wifi hardware ones espruino.
If I can get the core of this project just written in pure javascript I think I will be ok and can have a minifier create a web version and a espruino / or node js version (my code is in multiple files so this all needs to be put into one anyway I guess to work with espruino or node.
Thanks for the help offer I will certainly take you up on that when I get stuck hehe :)
-
• #22
Got called to special home cooked lunch... that's about the only thing that creates an interrupt of higher priority... ;)... back to business.
Developing with Espruino the way you do in a browser gets you straight into out-of-memory hell... or, what happened to me using the module folder with google closure compiler service 'too many compiles'.
There are several ways code can be loaded to Espruino: either direct in code or as module using require. With require you stick your code as a module into the modules folder as definable in the Web IDE. The advantage there is that code is (more) optimized when uploaded and uses much less memory... Also Espruino is different from any other JS virtual machine (VM) runtime environment in the way that it runs of the source: there is no Just In Time compilation into some internal VM (byte) code for execution... (therefore keep comments outside of functions... i like inline comments..., makes the code meta-readable). Anyway.
I would not make to much changes in your code... I would think of the canvas / context as a facade/adapter of either Espruino's Graphic library or as the controller board you intend to by by. I do not know which hardware you already have... Display? Controler? I'm sure though you have an Espruino 1.3b or 1.4 board that you run with Espruino 1v71 firmware, do you?
In the development process you start with the code in the Web IDE editor emulating a module and with very small buffers - just to get the algorithms going - and then, when it runs satisfactorily, you put it as module into the module folder and use the full buffers. This way you can develop and test nicely, and later run optimally in speed and as much application data memory as possible.
Btw, have you ever heard of require.js? It is a way of develop javascript application in a similar modular way with dependencies as java or c/c++. What language other than javascript are you familiar with?
Since we do not have an html page in Espruino, we quasi emulate the html page... I run the code from your ip address and looked at the html document. It is very simple: it is a single DOM node with the id canvas in which you create the canvas objects and... In the end you will will have exactly the same js files that you have now as modules and you load them with
instead of
<srcipt src="scriptFile.js"...```
(moduleName == scriptFile).To emulate the DOM / document and Canvas, you crate two extra modules where you stick the objects and methods into so you can run exactly the same code that you run in the browser.
As a first step, we have you get going on require.js... to load your js files with require. Then we
run it in the browser and do step by step develop the facade/adapter to the hardware you already
have. -
• #23
The hardware I will be using is.
3x http://www.embeddedadventures.com/led_matrix_display_LDP-6432.htmlHow I control this I am still trying to decide hehe. I have ordered one of these.
http://www.embeddedadventures.com/led_matrix_display_driver_plt-2001.htmlAnd raspberry pi
http://www.raspberrypi.org/products/model-a-plus/I also have a few stmf4 dev boards lying around hehe.
My three routes at the moment are run this javascript (converted version) in node js on a raspberry pi with a node i2c module and stream the data to the dmd controller board and have that take care of the dmd updates. (I will either modify or rewite the current firmware to use the i2c on the dmd board as im not 100% its supported yet)
Or get it running on a espruino board (will buy one once I can confirm i can run some form of this code on one hehe) and then stream the data again using i2c to dmd board
Or (I have experience with the stmf4) just write the code again from scratch in .c and bitbang the dmd my self.
I would like to use my javascript though as a few people around the office like using this project and I would like to continue to add features to it and then be able to create a version I can port to my hardware dmd.
I have little knowledge of node js I have wrote a few little scripts for it.
My language are as2/3,php,javascript and .cIf I am understanding you correct I can leave my project the way it is and use require js to load in the extra files and then override the canvas methods with my own custom byte arrays?
I am currently 30% to converting the javascript canvas with my own byte array one so I think I will continue and finish this hehe. Least it removes the whole html canvas dom problem.
Once that is complete I will be left with a project that has multiple files that will need to be loaded onto the espruino. How much ram does it have because my code does create quite a few little temporary canvas one being (2000*9*2)/8 large will this work at run time?
-
• #24
JavaScript has typed arrays / buffers that allow a very compact usage of the memory. I guess it could work... but I would rather use the display controller's memory and just ship commands and other stuff over there. So every canvas operation would just pass on the command to the controller and the controller actually creates then the bit stuff for fonts, etc... I need more understanding... Btw, could you also 'publish' the php file that serves the ajax call?
-
• #25
I'm not sure about the effort of conversion... even with a nice integrated development environment and a Espruino (or alike connected), there is not really a hot-swap possible. A single step is for sure there - @Gordon would for sure know. I use Chrome as my JS development runtime environment, Apache as my server environment, and some useful text editor (with less or more JavaScript and other support - such as TextWrangler...Brackets). I edit my files directly in a subfolder of Apache's Documents folder when using plain text editor/TextWranlger, Brackets has nice (preview) server integrated...
Getting to a setup for a cross develpment makes it fun: you will be able to run the very same app on the browser as well as in Espruino with - in kind of .c terms - just to load different #ifDef'd header files... Since you care most about the Canvas and its context, emulating that is not much that is needed.
Looking at your code I see that it is bottom line a set of functions. Making them objects would be my first step... it makes it more robust, easier to extend, and also easier to debug.
I pulled all your files... notice that the departure board is the last loaded js file and is the driver... (like in an SPA...). It makes the ajax request and gets all the things going. I assume that you have some php that actually goes and gets the data, because I cannot see any cross domain enablement CORS in the html page... this allows you to go directly after the data sourcing server and you do not need to go through php as the proxy server to respect the browsers sandbox / same origin policy (for security/safety purposes).
I also see that the departure board has DOM things in it... pulling this out makes it Espruino ready.
So there is some restructuring to be done, but - imho - it is useful and very helpful for moving on, also with extensions.
Since I do not have a LED panel, but I have a 320x240 TFT LCD display w/ touch screen, I'm thinking of making this my board and trying to get that done. I'm looking at my display as the canvas... so my adapter will take the Canvas commands/method calls and translate/adapt them into the Espruino Graphics methods/calls an run the same on my TFT LCD display as you run on your LED panel. The controller of my display has a scroll modus too - like the controler your thinking about - so refactoring/extracting the code and have it scrolled in code / canvas / screen controller is an interesting task. After all, the hardware and software are just subsystems communicating with each other. The interface stays the same, the implementation is platform dependent.
I have a little program written in javascript that displays information on a 192x32 pixel canvas. It also requests data from a php file on my server every min (So I will need WiFi, as I need the project to run standalone once complete).
Second part of this project is to display the javascript canvas on a real dot matrix display (I only use 3 colours) I am going to use three of these displays.
http://www.embeddedadventures.com/led_matrix_display_LDP-6432.html
To drive these displays you need some IO but for the data lines (x2) I want to use SPI to get the data out fast as possible. So I will need x2 SPI ports (Which are available) And I would like to use a UART based WiFi (As I need both SPI).
From experience I know driving dot matrix displays which need constant scanning to keep the image updated. You need a dedicated process to do this preferable running off a hardware interrupt timer so this process gets priority and the display will not freeze or look stuttery.
Does the js have access to these timers? Or can I write this part of the code in .c and send frame data to it from the js?
How fast is the SPI? same specs as the STM chip?
I have already written the project in javascript so would like to keep it in js. Any thoughts on if it would be possible to run it on this board. It needs to update the dot matrix at least 24fps.
Any thoughts would be much appreciated.