|
1 ========================================== |
|
2 HP 34970A Data Acquisition Unit - part 4 |
|
3 ========================================== |
|
4 |
|
5 :Author: David Douard |
|
6 :Category: Electronics |
|
7 :Tags: HP, 34970A, DMM, repair, test equipment |
|
8 :series: HP 34970A repair |
|
9 :series_index: 4 |
|
10 |
|
11 |
|
12 After a summer pause, I'm back on my HP34970A replair project. In |
|
13 `the previous post in this series <{filename}/hp34970a_3.rst>`_, I've |
|
14 started to reverse ingineer the serial protocol between the CPU board |
|
15 and the fonrt panel, and implement a prototype of replacement display. |
|
16 |
|
17 |
|
18 OLED display |
|
19 ============ |
|
20 |
|
21 I bought the bigest OLED display I could find (at a reasonable price) |
|
22 that would fit in the front panel assembly. It's a `blue 256x64 OLED |
|
23 display`_ drived by a SSD1322 controler. |
|
24 |
|
25 .. _`blue 256x64 OLED display`: http://www.buydisplay.com/default/oled-3-2-inch-displays-module-companies-with-driver-circuit-blue-on-black |
|
26 |
|
27 .. image:: {filename}/images/hp34970a/oled_module.jpg |
|
28 :alt: 3"2 blue OLED module used as a replacement display for the HP34970A. |
|
29 |
|
30 My first problem was to drive the display from my Nucleo board. I |
|
31 couldn't find graphic library that worked directly. I was already |
|
32 using the UniGraphic_ library with the small TFT display, so I decided |
|
33 to implement support for this OLED module in the library. |
|
34 |
|
35 .. _UniGraphic: https://developer.mbed.org/teams/GraphicsDisplay/code/UniGraphic |
|
36 |
|
37 I spent quite some time to make this work for several reasons, among |
|
38 others: |
|
39 |
|
40 - I was first using my Nucleo F031K6 board; it's nice, it's small, but |
|
41 it only have 4k of RAM, so the malloc I as doing in my test code to |
|
42 allocate the "framebuffer" in which drawings are done before being |
|
43 tranferred to the display module... well let's say if I took time to |
|
44 check the return value of the malloc call (which one should always |
|
45 do, even on small embedded devices), I would have not lost a couple |
|
46 of hours, so to speak (tip: allocating 8k in a 4k RAM will not fit), |
|
47 |
|
48 - The SSD1322 controller is *reasonnably* well documented, but what's |
|
49 not documented is how it is used on the OLED display... In fact, |
|
50 once I could at least see some pixels on my display, I spent quite |
|
51 some time trying to control where my pixels are located on the |
|
52 module. There is not that much demo material available for this |
|
53 module besides a `poorly written sample C code`_ (in a .txt file!) |
|
54 for the 80C51 processor. What's hidden in this file (which I could |
|
55 not fing any where else) is the magic 0x1C value which must be given |
|
56 as first argument to the SET_COLUMN_ADDR "function" of the SSD1322. |
|
57 |
|
58 - I also lost some time trying to implement the support for this module |
|
59 as a class derived from UniGraphic's `LCD class`_ (like several |
|
60 other supported modules like the SSD1306_), but that was a mistake, |
|
61 since this kind of OLED module is too different from both a TFT |
|
62 display or a monochrome LCD display. So I've reimplemented the class |
|
63 as a derived class of the GraphicDisplay_. This work is far for being |
|
64 finished yet (and ready for a *Pull Request* to submit to the |
|
65 UniGrahic project), but at least, I can continue my work on the |
|
66 HP34970's display. |
|
67 |
|
68 |
|
69 .. _`LCD class`: https://developer.mbed.org/teams/GraphicsDisplay/code/UniGraphic/file/tip/Display/LCD.h |
|
70 .. _SSD1306: https://developer.mbed.org/teams/GraphicsDisplay/code/UniGraphic/file/tip/Inits/SSD1306.h |
|
71 .. _GraphicDisplay: https://developer.mbed.org/teams/GraphicsDisplay/code/UniGraphic/file/tip/Graphics/GraphicsDisplay.h |
|
72 .. _`poorly written sample C code`: http://www.buydisplay.com/download/democode/ER-OLEDM032-1_DemoCode.txt |
|
73 |
|
74 |
|
75 Improving the serial sniffer |
|
76 ============================ |
|
77 |
|
78 Once I could draw pixels on my OLED module, I put this code in my |
|
79 existing prototype replacing the simple display code I used with the |
|
80 TFT module. |
|
81 |
|
82 And one problem I already had with the previous "working" prototype |
|
83 became bigger: I was missing many characters on the serial bus between |
|
84 the CPU and the front panel. |
|
85 |
|
86 My first implementation of the protocol sniffing was very tedious and |
|
87 poorly written. It was not reading at all the traffic on the Tx line |
|
88 (ie the key strokes), so I was never sure if a 0x66 was the beginning |
|
89 of a transmission or some payload for which I missed the beginning. |
|
90 |
|
91 Using the interrupt-based (asynchronous) BufferedSerial_ |
|
92 implementation did not help that much. |
|
93 |
|
94 So I rewrote this part of the using 2 serial ports, using only the Rx |
|
95 line on both of them, one plugged on the Rx line of the serial |
|
96 communication, and the other on the Tx line of this comm. Doing so I |
|
97 can sniff the whole communication between the CPU and the display |
|
98 panel and make a way better protocol interpreter. |
|
99 |
|
100 The result was way better than before, and now I was able to detect |
|
101 the protocol interpretation errors, but still, I was missing many |
|
102 parts of the transmission. |
|
103 |
|
104 I ended up to figure that the culprit was my |
|
105 ``SSD1322::copy_to_lcd()`` method: it takes almost 20ms to transmit |
|
106 the whole display content the module. And with the way my code was |
|
107 written, even with interrupt driven serial handlers, these interrupt |
|
108 were not captured during the execution of this copy routine. |
|
109 |
|
110 At this point, I've started to read a bit more the asynchronous and |
|
111 event driven APIs of the mbed platform, but could not clearly see a |
|
112 pattern to prevent this long "frozen" periods during which I was |
|
113 unable to capture serial communications. |
|
114 |
|
115 .. _BufferedSerial: https://developer.mbed.org/users/sam_grove/code/BufferedSerial/ |
|
116 |
|
117 I was almost ready to use 2 microcontrollers for the job: one to sniff |
|
118 and interpret the serial communication and one to drive the display. |
|
119 |
|
120 .. image:: {filename}/images/hp34970a/poc_oled.jpg |
|
121 :alt: Improvment of the POC based on the Nucleo F446RE and using a blue OLED module. |
|
122 |
|
123 Improving the tasks |
|
124 =================== |
|
125 |
|
126 But I've discovered a few days ago that the RTOS project is now part |
|
127 of the mbed platform, allowing to use threads instead of pure event |
|
128 driven code. So I tried to put the copy_to_lcd routine executions in a |
|
129 dedicated thread, and bingo, I've got now something that begins to |
|
130 work enough to make it usable: |
|
131 |
|
132 .. dailymotion:: x4tib5s |
|
133 :width: 270 |
|
134 :height: 480 |
|
135 |
|
136 |
|
137 What's next |
|
138 =========== |
|
139 |
|
140 There is still a lot of work to do: |
|
141 |
|
142 - improve the display reactivity: I'll probably try to implement |
|
143 partial copy of the display instead of sending the whole |
|
144 "framebuffer" each time something is changed on the display (the |
|
145 SSD1322 allows to specify a "window" in which to send data), |
|
146 |
|
147 - improve overall display organisation and find the missing flags (I |
|
148 still have not found the flag values for OC, MIN, MAX, AVG, ONCE, |
|
149 AUTO and MEM), |
|
150 |
|
151 - try to install the display module and the Nucleo board in the front |
|
152 panel assembly (I don't want to go for a specifically designed PCB, |
|
153 at least for now), |
|
154 |
|
155 - publish the code. |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |