diff -r d9cdcb4576c0 -r 70aad9a1272b content/hp34970a_4.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/content/hp34970a_4.rst Sat Sep 17 02:08:03 2016 +0200 @@ -0,0 +1,161 @@ +========================================== + HP 34970A Data Acquisition Unit - part 4 +========================================== + +:Author: David Douard +:Category: Electronics +:Tags: HP, 34970A, DMM, repair, test equipment +:series: HP 34970A repair +:series_index: 4 + + +After a summer pause, I'm back on my HP34970A replair project. In +`the previous post in this series <{filename}/hp34970a_3.rst>`_, I've +started to reverse ingineer the serial protocol between the CPU board +and the fonrt panel, and implement a prototype of replacement display. + + +OLED display +============ + +I bought the bigest OLED display I could find (at a reasonable price) +that would fit in the front panel assembly. It's a `blue 256x64 OLED +display`_ drived by a SSD1322 controler. + +.. _`blue 256x64 OLED display`: http://www.buydisplay.com/default/oled-3-2-inch-displays-module-companies-with-driver-circuit-blue-on-black + +.. image:: {filename}/images/hp34970a/oled_module.jpg + :alt: 3"2 blue OLED module used as a replacement display for the HP34970A. + +My first problem was to drive the display from my Nucleo board. I +couldn't find graphic library that worked directly. I was already +using the UniGraphic_ library with the small TFT display, so I decided +to implement support for this OLED module in the library. + +.. _UniGraphic: https://developer.mbed.org/teams/GraphicsDisplay/code/UniGraphic + +I spent quite some time to make this work for several reasons, among +others: + +- I was first using my Nucleo F031K6 board; it's nice, it's small, but + it only have 4k of RAM, so the malloc I as doing in my test code to + allocate the "framebuffer" in which drawings are done before being + tranferred to the display module... well let's say if I took time to + check the return value of the malloc call (which one should always + do, even on small embedded devices), I would have not lost a couple + of hours, so to speak (tip: allocating 8k in a 4k RAM will not fit), + +- The SSD1322 controller is *reasonnably* well documented, but what's + not documented is how it is used on the OLED display... In fact, + once I could at least see some pixels on my display, I spent quite + some time trying to control where my pixels are located on the + module. There is not that much demo material available for this + module besides a `poorly written sample C code`_ (in a .txt file!) + for the 80C51 processor. What's hidden in this file (which I could + not fing any where else) is the magic 0x1C value which must be given + as first argument to the SET_COLUMN_ADDR "function" of the SSD1322. + +- I also lost some time trying to implement the support for this module + as a class derived from UniGraphic's `LCD class`_ (like several + other supported modules like the SSD1306_), but that was a mistake, + since this kind of OLED module is too different from both a TFT + display or a monochrome LCD display. So I've reimplemented the class + as a derived class of the GraphicDisplay_. This work is far for being + finished yet (and ready for a *Pull Request* to submit to the + UniGrahic project), but at least, I can continue my work on the + HP34970's display. + + +.. _`LCD class`: https://developer.mbed.org/teams/GraphicsDisplay/code/UniGraphic/file/tip/Display/LCD.h +.. _SSD1306: https://developer.mbed.org/teams/GraphicsDisplay/code/UniGraphic/file/tip/Inits/SSD1306.h +.. _GraphicDisplay: https://developer.mbed.org/teams/GraphicsDisplay/code/UniGraphic/file/tip/Graphics/GraphicsDisplay.h +.. _`poorly written sample C code`: http://www.buydisplay.com/download/democode/ER-OLEDM032-1_DemoCode.txt + + +Improving the serial sniffer +============================ + +Once I could draw pixels on my OLED module, I put this code in my +existing prototype replacing the simple display code I used with the +TFT module. + +And one problem I already had with the previous "working" prototype +became bigger: I was missing many characters on the serial bus between +the CPU and the front panel. + +My first implementation of the protocol sniffing was very tedious and +poorly written. It was not reading at all the traffic on the Tx line +(ie the key strokes), so I was never sure if a 0x66 was the beginning +of a transmission or some payload for which I missed the beginning. + +Using the interrupt-based (asynchronous) BufferedSerial_ +implementation did not help that much. + +So I rewrote this part of the using 2 serial ports, using only the Rx +line on both of them, one plugged on the Rx line of the serial +communication, and the other on the Tx line of this comm. Doing so I +can sniff the whole communication between the CPU and the display +panel and make a way better protocol interpreter. + +The result was way better than before, and now I was able to detect +the protocol interpretation errors, but still, I was missing many +parts of the transmission. + +I ended up to figure that the culprit was my +``SSD1322::copy_to_lcd()`` method: it takes almost 20ms to transmit +the whole display content the module. And with the way my code was +written, even with interrupt driven serial handlers, these interrupt +were not captured during the execution of this copy routine. + +At this point, I've started to read a bit more the asynchronous and +event driven APIs of the mbed platform, but could not clearly see a +pattern to prevent this long "frozen" periods during which I was +unable to capture serial communications. + +.. _BufferedSerial: https://developer.mbed.org/users/sam_grove/code/BufferedSerial/ + +I was almost ready to use 2 microcontrollers for the job: one to sniff +and interpret the serial communication and one to drive the display. + +.. image:: {filename}/images/hp34970a/poc_oled.jpg + :alt: Improvment of the POC based on the Nucleo F446RE and using a blue OLED module. + +Improving the tasks +=================== + +But I've discovered a few days ago that the RTOS project is now part +of the mbed platform, allowing to use threads instead of pure event +driven code. So I tried to put the copy_to_lcd routine executions in a +dedicated thread, and bingo, I've got now something that begins to +work enough to make it usable: + +.. dailymotion:: x4tib5s + :width: 270 + :height: 480 + + +What's next +=========== + +There is still a lot of work to do: + +- improve the display reactivity: I'll probably try to implement + partial copy of the display instead of sending the whole + "framebuffer" each time something is changed on the display (the + SSD1322 allows to specify a "window" in which to send data), + +- improve overall display organisation and find the missing flags (I + still have not found the flag values for OC, MIN, MAX, AVG, ONCE, + AUTO and MEM), + +- try to install the display module and the Nucleo board in the front + panel assembly (I don't want to go for a specifically designed PCB, + at least for now), + +- publish the code. + + + + + +