Spark Logic

[SOLVED] Enable interrupts from inside a timer interrupt

castortiu Tue Jan 16, 2018 1:45 am

Hi there,

I need to start a timer and make it fire from inside another timer interrupt, basically I need another timer to fire even when the other timer calls has not finished.

Seems that HardwareTimer disable interrupts when it fires because inside timer 2 I start timer 3 but it doesn’t fire until immediate the call to the timer 2 has finished.

The sample below is way oversimplified, but my case is that I need to start timer A when it fires I need to start timer B however timer B may need to fire before the call to A has finished.

Long story short I need to control the brightness of my RGBMatrix, and to do that I need to control the matrix OE (OutputEnable) leg time, however I cannot start this timer until the latch from the last frame has been made, Timer A triggers the latch to make it visible on the matrixx and then proceeds to build the next frame, meanwhile Timer B has to start after the latch and has to be called(fired) to disable OE at an specific time to disable the matrix output.

Hopefully I made myself clear, but the question is very simple, I need to enable interruptions re-entrancy which seems HardwareTimer disables when the interruption fires.

I tried to put interrupts() as first line inside void ISRUpdate but nothing change, ISRUpdate1 is called as soon ISRUpdate finish;
HardwareTimer timerDisplay(2);
HardwareTimer timerDisplayEnabled(3);

timerDisplay.setMode(0, TIMER_OUTPUT_COMPARE);
timerDisplay.setPeriod(100 * microseconds_per_millisecond);
timerDisplay.attachInterrupt(0, ISRUpdate);
timerDisplay.resume();

timerDisplayEnabled.setMode(0, TIMER_OUTPUT_COMPARE);
timerDisplayEnabled.setPeriod(5);
timerDisplayEnabled.attachInterrupt(0, ISRUpdate1);
timerDisplayEnabled.pause();

bool myValue = false;

void ISRUpdate(void)
{
timerDisplay.pause();
…
…
…
timerDisplayEnabled.setPeriod(brightness); // about 100
timerDisplayEnabled.resume();
…
…
// Code in here runs for 500 microseconds, 5x more than the time in the line above
…
…
timerDisplay.setPeriod(XX);
timerDisplay.resume();

// value of myValue still is false, interrupt for timerDisplayEnabled doesn’t trigger until ISRUpdate which was called from the timer 2
// unwind from the stack.
}

void ISRUpdate1(void)
{
timerDisplayEnabled.pause();
myValue = true;
}

Replies

dannyf Fri Jan 19, 2018 12:30 pm

if it has serial inputs, a latch and an OE pin, it is likely that it is based on serial shifters like HC595 where the OE pin is completely unhinged from the input circuitry.

implementing ppm over pwm hardware just makes zero sense.

castortiu Fri Jan 19, 2018 6:07 pm

Yes, most of these matrix are based on shift register. And have different scan lines.
Most usual is 1/16. Means it has 4 lines A,B,,C,D to control the row 1-16- & 17-32, so if the address is 0b0001 then data will be sent to row 1 AND 17, however has two data lines per color R1, R2, G1, G2, B1, B2 so after every latch every change in address plus the 6 data lines to control colors in two rows at the same time, there are other matrix that are 1/32 Means that address lines are A,B,C,D,E and just R,B,G, however 1/32 are great to control matrix of 64 rows since usually have an extra address line A, B,C,D, E and R1, R2, G1, G2, B1,

beyond the address and data bus there are 3 more lines, latch, clock outputenable

Start to set the address/data while sending the train of clock pulses (128 for 128 columns), then latching sends the data to the LEDs.
Output enable is just a switch to “turnon/turnoff” the whole display.

To making it very simple, how would you implement a PWM control with 1 row, 8 columns, 16 tones, monochromatic at 250Hz refresh rate with 3 wires? After that is just a question of scale.

Basically you have 3 wires to control 8 LEDs in a row
R – Data line
L – Latch
C – Clock

dannyf Fri Jan 19, 2018 7:37 pm

looks like yours has a 16:4 mux that controls which line is on, and then 3 sets of shift registers, for R/G/B.

if I were to write a driver for this, I would establish a buffer: it contains information about the display’s construction (including current frame index, or brightness) and frames. If you write a slave receiver here (spi or uart), you can turn the controller-less display into a common / universal display and commercialize it potentially. In that set-up, the master can simply communicate to the display unit with command data + images and the slave will handle the rest.

each frame then contains a current index for the line being scanned.

a display routine is periodically called from the isr. The display routine would perform something like this:

1) fill the shift registers with line data;
2) turn on the current mux line; this assumes that the mux lines cannot be turned off.
3) strobe out the shift register data;
4) advance the line index to the next line;

the logic is slightly different if you use DMA under-run interrupt in step 1) above.

Your OE line is driven separately via a pwm module – using the OE pin to a PWM a HC595 has been done for ages.

You can take a look at this basic logic at work here (https://dannyelectronics.wordpress.com/ … ment-leds/) and here (https://dannyelectronics.wordpress.com/ … ment-leds/) and here (https://wordpress.com/post/dannyelectro … s.com/4113).

The actual implementation will be different, the hardware involved will be different but the basic logic is the same.

castortiu Sat Jan 20, 2018 2:21 am

“if I were to write a driver for this, I would establish a buffer: it contains information about the display’s construction (including current frame index, or brightness) and frames. If you write a slave receiver here (spi or uart), you can turn the controller-less display into a common / universal display and commercialize it potentially. In that set-up, the master can simply communicate to the display unit with command data + images and the slave will handle the rest.”

If you look at my previous posts with Steve about slave DMA SPI this is exactly what the blue pill job does, it is a RGB Matrix rendering driver :)

The blue pill only function for me is use the SPI bus to take an input of ARGB (1555) frames and display them on the matrix, internally is using a DMA buffer for SPI and double buffer for the Matrix data to avoid tearing of the screen, doing this way I have the whole ESP8266 CPU to create frames with my graphic library as the Clock, Animations, blending, effects, OSD (on screen display) with alpha support, etc and then send the frame as is to the blue pill where it take care of encoding the ARGB (1555) frame into whatever the matrix understands, in this case RGB (444)

In fact I can disconnect the ESP8266 from the STM and the last frame will keep rendering on the matrix, also the SPI bus is full-duplex where I can send instructions from the ESP as get/set rtc, set the brightness of the display from the ESP8266 or control other things like the buzzer (STM also has coded a tone synthesizer that is driven over the same SPI bus), the STM DMA bus also is driven with an interruption over the CS so the DMA buffer self-heal when receives corrupted data, also has other cool features as partitions of frames since sending a full frame from the ESP would take some time and the STM will take some time to decode a full frame as well, this synchronization would slow down the two CPUs, instead the ESP8266 sends 1/8 of a frame at the time arbitrarily so the SPI burst transition from ESP to STM is very short and give time to the STM to decode 1/8 of a frame while is receiving another 1/8 frame in the DMA buffer in parallel.

This behaviors allow as very high speed animation to automatically omit sending some portion of the frame since a new 1/8 of frame is coming behind, means the animation will never be slow down because of the CPU processing, collateral effect will be that just some frames may be skipped, that’s all

Your 4 points seems a generalization how to do it however doesn’t share any hint or mechanic how pwm is used to give different tones for every pixel, still reading what you mean, also I’ll go over all the links, however if I can understand well the following, then I can scale it as well,

PWM with 3 wires to control 8 LEDs in a row
R – Data line
L – Latch
C – Clock

With BCM I need only 4 very short clock pulses plus 4 latches to display a pixel with 16 tones. In the case of 128 columns just 128×4 clocks plus 4 latches. how many clock cycles and latch do you need to display a pixel with 16 tones with PWM?

castortiu Sat Jan 20, 2018 5:48 am

By the way I did work with shift registers as well, that’s not new to me, in fact my first raw Red Matrix version about 3 months ago was using 74hc595d discrete components and did good progress, I made work the matrix in the image below with an Arduino nano for a 24×32 just red channel a 60Hz, 16 tones of red using my own PWM algorithm, until I found out that I could get from China fully assembled RGB panels 128×32 with the controllers embedded for about the same price, so there was no way I could make something even remotely close similar myself for the same price so I redirected my effort on understand and make the matrix works, using my own PWM algorithm discovered that I would need something at least 100 times more powerful than the Arduino nano to make it work there is where I found the STM32 and start to post here :)

The research lead me to BCM, I know my own PWM implementation sucks, and I’m interested to know what you have in mind at this scale. Remember that the matrix is 128×32 and has 6 shift registers R1, R2, G1, G2, B1, B2 and want to have high refresh rate, so the PWM algorithm needs to be very efficient, most than everything I’m interested to learn an efficient PWM technique.

If I would use my own and old PWM algorithm I would need 128 clocks * 16 latches, that would be almost 4 times greater than BCM and basically probably I could get only 60Hz instead 250Hz.

The original idea in the images below was to chain 74hc595d controllers vertically and horizontally to control a larger Matrix 128×32 and replacing only the MCU, so naive myself that I thought with 16Mhz was enough to do all that.

zmemw16 Sat Jan 20, 2018 2:47 pm

please tell us(me) how those pcb’s were made ?
couple by etch resist pen hand drawn ?
and the ones with very, very clean isolation cuts ?
stephen

dannyf Sat Jan 20, 2018 2:54 pm

o the PWM algorithm needs to be very efficient

that’s probably the disconnect. Take a look at hc595’s datasheet and see how the OE pin works with respect to the rest of the circuitry.

dannyf Sat Jan 20, 2018 2:56 pm

20180119_211651.jpg (241.71 KiB)

for large matrix, that’s a pin efficient but not time efficient implementation: as the row data is serial as well.

a better approach is to use a mux (or multiples of them).

castortiu Sat Jan 20, 2018 3:50 pm

“please tell us(me) how those pcb’s were made ?”

Started with electronics again as a hobby about 5 months ago after 20 years of doing nothing with electronics so I was trying to find a quick method to iterate and create prototypes.

1) The board in the center was made with paper toner transfer and etching with ferric chloride, I tried about 10 different methods, I never could master the process, even bought new printers, papers, chemicals and so on, big failure so far, always for one reason or another some toner is not transferred and had to hand touch with a pen, as you can see in the image I sent before. Currently the boards I do with toner transfer are not all bad however I cannot go below 80mil traces, unusable unless is a very basic PCB.

2) The PCBs on the side are made with a CNC machine, these were made about 30 days after trying many techniques with the machine, at first they were a mess and started to improve the technique, probably I did about 100 PCBs until vastly improved the technique, these boards are old, at this moment after 5 months I “mastered” the process and I do my double side PCBs with a 15mil traces and they look 10 times better than the picture above.

3) Started to play with Pre-sensitized PCBs, transparencies and UV light, however Pre-sensitized PCBs are way too expensive, so dropped this technique in favor of the CNC machine, however Pre-sensitized PCBs can gain quite a bit of time for complex PCBs since the CNC machine can be working for 1hr or more for every side.

These are some of the keys in the technique I’m using.
a – Use good carving bit with a .1mm tip
b – Center the carving bit with a strobe light
c – Make a thing layer of WD40 while the machine is carbing
d – Pre-level the work surface
e – Secure the PCB to the machine very flat using double side tape.
f – Autolevel algorithm to measure imperfections of the PCB and readjust bit height in the source file

At this moment my CNC machine carves only 0.05mm from the copper, so the carving bit barely touch the fiber glass.

I’ll see if I find new PCBs to show how they looks like, they are really good at this time.

This is the machine I got:
https://www.ebay.com/itm/USB-3Axis-CNC- … 25e8de4d39

I had to make some modifications to the machine to add an autolevel input since by default these machine do not have them.

Sign in to reply