- Tue Jul 18, 2017 7:48 am
#68309
I still struggle with generating a stable pulse for the LED signal ... I've now protected it with a RC high-pass filter, so it won't be dangerous for the LEDs anymore if it stayed HIGH for any reason... So I now tried to manage the LED signal via Software.
Since I only need a short pulse, I used the routine that prepares the SPI buffer for timing the LED pulse:
Code: Select all#define LED_LOW GPOC = 1 << 12;
#define LED_HIGH GPOS = 1 << 12;
noInterrupts();
LED_HIGH;
if (FrameBufferLayout == 0) {
// unwrapped for loop for faster execution
rowBuffer[0] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[0] + rowOffset];
rowBuffer[1] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[1] + rowOffset];
if (ledPulseWidth == 0) LED_LOW;
rowBuffer[2] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[2] + rowOffset];
rowBuffer[3] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[3] + rowOffset];
if (ledPulseWidth == 1) LED_LOW;
rowBuffer[4] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[4] + rowOffset];
rowBuffer[5] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[5] + rowOffset];
if (ledPulseWidth == 2) LED_LOW;
rowBuffer[6] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[6] + rowOffset];
rowBuffer[7] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[7] + rowOffset];
if (ledPulseWidth == 3) LED_LOW;
rowBuffer[8] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[8] + rowOffset];
rowBuffer[9] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[9] + rowOffset];
if (ledPulseWidth == 4) LED_LOW;
rowBuffer[10] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[10] + rowOffset];
rowBuffer[11] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[11] + rowOffset];
if (ledPulseWidth == 5) LED_LOW;
rowBuffer[12] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[12] + rowOffset];
rowBuffer[13] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[13] + rowOffset];
if (ledPulseWidth == 6) LED_LOW;
rowBuffer[14] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[14] + rowOffset];
rowBuffer[15] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[15] + rowOffset];
if (ledPulseWidth == 7) LED_LOW;
rowBuffer[16] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[16] + rowOffset];
rowBuffer[17] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[17] + rowOffset];
if (ledPulseWidth == 8) LED_LOW;
rowBuffer[18] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[18] + rowOffset];
rowBuffer[19] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[19] + rowOffset];
if (ledPulseWidth == 9) LED_LOW;
rowBuffer[20] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[20] + rowOffset];
rowBuffer[21] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[21] + rowOffset];
if (ledPulseWidth == 10) LED_LOW;
rowBuffer[22] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[22] + rowOffset];
rowBuffer[23] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[23] + rowOffset];
if (ledPulseWidth == 11) LED_LOW;
rowBuffer[24] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[24] + rowOffset];
rowBuffer[25] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[25] + rowOffset];
if (ledPulseWidth == 12) LED_LOW;
rowBuffer[26] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[26] + rowOffset];
rowBuffer[27] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[27] + rowOffset];
if (ledPulseWidth == 13) LED_LOW;
rowBuffer[28] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[28] + rowOffset];
rowBuffer[29] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[29] + rowOffset];
if (ledPulseWidth == 14) LED_LOW;
rowBuffer[30] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[30] + rowOffset];
rowBuffer[31] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[31] + rowOffset];
if (ledPulseWidth == 15) LED_LOW;
rowBuffer[32] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[32] + rowOffset];
rowBuffer[33] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[33] + rowOffset];
if (ledPulseWidth == 16) LED_LOW;
rowBuffer[34] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[34] + rowOffset];
rowBuffer[35] = FrameBufferInvert ^ displayBuffer[RowByteSelectorH[35] + rowOffset];
}
LED_LOW;
interrupts();
This is just the relevant part of the code that gets executed every 100µs / 10kHz by timer1 interrupt.
With this code, I can vary the pulse up to 4µs (I might turn the LED on little earlier in the code to get pulses up to 10µs but the principle is the same).
However, the LEDs flicker noticeably
At least 10 times a second I get an LED pulse that is ~20µs long, so I guess the code gets interrupted...
Is there a way to solve that issue? Either stop interruption within that section, or still find a suitable hardware component of the ESP8266 to generate the pulse?
I already use GPIO 13,14,15 for SPI and currently 12 for LED... It really would be nice if the pin wouldn't interfere with programming via UART
Another disadvantage of the code above is, that I will have to use 10% of CPU (10µs every 100µs) to get my desired LED pulse. I would be able to optimize the code to only consume ~3% if it wouldn't have to toggle the LED pin.
Edit: Just fount out that
Code: Select all LED_HIGH;
delayMicroseconds(ledPulseWidth);
LED_LOW;
results in a stable pulse that doesn't get interrupted. But that is obviously the worst thing to do
However, it might be a solution... 10% CPU just for the LED pulse, another ~4% for preparing SPI data... Still ~86% left for wifi stack and my own application code.