Skip to content

Commit 1b9ad12

Browse files
author
bitluni
committed
Merge branch 'master' of https://github.com/bitluni/ESP32Lib
2 parents a939653 + 084cf1a commit 1b9ad12

File tree

5 files changed

+188
-113
lines changed

5 files changed

+188
-113
lines changed

src/I2S/I2S.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,21 @@ I2S::I2S(const int i2sIndex)
3232
void IRAM_ATTR I2S::interruptStatic(void *arg)
3333
{
3434
volatile i2s_dev_t &i2s = *i2sDevices[((I2S *)arg)->i2sIndex];
35-
i2s.int_clr.val = i2s.int_raw.val;
36-
((I2S *)arg)->interrupt();
35+
//i2s object not safely accesed in DRAM or IRAM
36+
//i2s.int_clr.val = i2s.int_raw.val;
37+
//using REG_WRITE to clear the interrupt instead
38+
//note: there are still other alternatives, see i2s driver .c file
39+
//inside the i2s_intr_handler_default() function
40+
REG_WRITE(I2S_INT_CLR_REG(((I2S *)arg)->i2sIndex), (REG_READ(I2S_INT_RAW_REG(((I2S *)arg)->i2sIndex)) & 0xffffffc0) | 0x3f);
41+
//the call to the overloaded (or any) non-static member function definitely breaks the IRAM rule
42+
// causing an exception when concurrently accessing the flash (or flash-filesystem) or wifi
43+
//the reason is unknown but probably related with the compiler instantiation mechanism
44+
//(note: defining the code of the [member] interrupt function outside the class declaration,
45+
// and with IRAM flag does not avoid the crash)
46+
//((I2S *)arg)->interrupt();
47+
48+
if(((I2S *)arg)->interruptStaticChild)
49+
((I2S *)arg)->interruptStaticChild(arg);
3750
}
3851

3952
void I2S::reset()

src/I2S/I2S.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ class I2S
5353
void deleteDMABuffers();
5454
virtual void getClockSetting(long *sampleRate, int *n, int *a, int *b, int *div);
5555

56+
void (*interruptStaticChild)(void *arg) = 0;
57+
5658
protected:
57-
virtual void interrupt() = 0;
5859
virtual bool useInterrupt();
5960
void setAPLLClock(long sampleRate, int bitCount);
6061
void setClock(long sampleRate, int bitCount, bool useAPLL = true);

src/VGA/VGA14BitI.h

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@
1515

1616
class VGA14BitI : public VGA, public GraphicsR5G5B4A2
1717
{
18-
public:
18+
public:
1919
VGA14BitI(const int i2sIndex = 1)
2020
: VGA(i2sIndex)
2121
{
22+
interruptStaticChild = &VGA14BitI::interrupt;
2223
}
2324

2425
bool init(const Mode &mode,
@@ -32,17 +33,10 @@ class VGA14BitI : public VGA, public GraphicsR5G5B4A2
3233
G0Pin, G1Pin, G2Pin, G3Pin, G4Pin,
3334
B0Pin, B1Pin, B2Pin, B3Pin,
3435
hsyncPin, vsyncPin
35-
};
36+
};
3637
return VGA::init(mode, pinMap, 16, clockPin);
3738
}
3839

39-
bool init(const Mode &mode, const PinConfig &pinConfig)
40-
{
41-
int pins[16];
42-
pinConfig.fill14Bit(pins);
43-
return VGA::init(mode, pins, 16, pinConfig.clock);
44-
}
45-
4640
bool init(const Mode &mode, const int *redPins, const int *greenPins, const int *bluePins, const int hsyncPin, const int vsyncPin, const int clockPin = -1)
4741
{
4842
int pinMap[16];
@@ -58,6 +52,13 @@ class VGA14BitI : public VGA, public GraphicsR5G5B4A2
5852
return VGA::init(mode, pinMap, 16, clockPin);
5953
}
6054

55+
bool init(const Mode &mode, const PinConfig &pinConfig)
56+
{
57+
int pins[16];
58+
pinConfig.fill14Bit(pins);
59+
return VGA::init(mode, pins, 16, pinConfig.clock);
60+
}
61+
6162
virtual void initSyncBits()
6263
{
6364
hsyncBitI = mode.hSyncPolarity ? 0x4000 : 0;
@@ -99,19 +100,63 @@ class VGA14BitI : public VGA, public GraphicsR5G5B4A2
99100
Graphics::show(vSync);
100101
}
101102

102-
protected:
103-
virtual bool useInterrupt()
103+
protected:
104+
bool useInterrupt()
104105
{
105106
return true;
106107
};
107108

108-
void interruptPixelLine(int y, unsigned long *pixels, unsigned long syncBits)
109+
static void interrupt(void *arg);
110+
111+
static void interruptPixelLine(int y, unsigned long *pixels, unsigned long syncBits, void *arg);
112+
};
113+
114+
115+
void IRAM_ATTR VGA14BitI::interrupt(void *arg)
116+
{
117+
VGA14BitI * staticthis = (VGA14BitI *)arg;
118+
119+
unsigned long *signal = (unsigned long *)staticthis->dmaBufferDescriptors[staticthis->dmaBufferDescriptorActive].buffer();
120+
unsigned long *pixels = &((unsigned long *)staticthis->dmaBufferDescriptors[staticthis->dmaBufferDescriptorActive].buffer())[(staticthis->mode.hSync + staticthis->mode.hBack) / 2];
121+
unsigned long base, baseh;
122+
if (staticthis->currentLine >= staticthis->mode.vFront && staticthis->currentLine < staticthis->mode.vFront + staticthis->mode.vSync)
109123
{
110-
unsigned short *line = frontBuffer[y];
111-
for (int i = 0; i < mode.hRes / 2; i++)
124+
baseh = (staticthis->hsyncBit | staticthis->vsyncBit) * 0x10001;
125+
base = (staticthis->hsyncBitI | staticthis->vsyncBit) * 0x10001;
126+
}
127+
else
128+
{
129+
baseh = (staticthis->hsyncBit | staticthis->vsyncBitI) * 0x10001;
130+
base = (staticthis->hsyncBitI | staticthis->vsyncBitI) * 0x10001;
131+
}
132+
for (int i = 0; i < staticthis->mode.hSync / 2; i++)
133+
signal[i] = baseh;
134+
for (int i = staticthis->mode.hSync / 2; i < (staticthis->mode.hSync + staticthis->mode.hBack) / 2; i++)
135+
signal[i] = base;
136+
137+
int y = (staticthis->currentLine - staticthis->mode.vFront - staticthis->mode.vSync - staticthis->mode.vBack) / staticthis->mode.vDiv;
138+
if (y >= 0 && y < staticthis->mode.vRes)
139+
staticthis->interruptPixelLine(y, pixels, base, arg);
140+
else
141+
for (int i = 0; i < staticthis->mode.hRes / 2; i++)
112142
{
113-
//writing two pixels improves speed drastically (avoids memory reads)
114-
pixels[i] = syncBits | (line[i * 2 + 1] & 0x3fff) | ((line[i * 2] & 0x3fff) << 16);
143+
pixels[i] = base | (base << 16);
115144
}
145+
for (int i = 0; i < staticthis->mode.hFront / 2; i++)
146+
signal[i + (staticthis->mode.hSync + staticthis->mode.hBack + staticthis->mode.hRes) / 2] = base;
147+
staticthis->currentLine = (staticthis->currentLine + 1) % staticthis->totalLines;
148+
staticthis->dmaBufferDescriptorActive = (staticthis->dmaBufferDescriptorActive + 1) % staticthis->dmaBufferDescriptorCount;
149+
if (staticthis->currentLine == 0)
150+
staticthis->vSyncPassed = true;
151+
}
152+
153+
void IRAM_ATTR VGA14BitI::interruptPixelLine(int y, unsigned long *pixels, unsigned long syncBits, void *arg)
154+
{
155+
VGA14BitI * staticthis = (VGA14BitI *)arg;
156+
unsigned short *line = staticthis->frontBuffer[y];
157+
for (int i = 0; i < staticthis->mode.hRes / 2; i++)
158+
{
159+
//writing two pixels improves speed drastically (avoids memory reads)
160+
pixels[i] = syncBits | (line[i * 2 + 1] & 0x3fff) | ((line[i * 2] & 0x3fff) << 16);
116161
}
117-
};
162+
}

src/VGA/VGA3BitI.h

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class VGA3BitI : public VGA, public GraphicsR1G1B1A1
1919
VGA3BitI() //8 bit based modes only work with I2S1
2020
: VGA(1)
2121
{
22+
interruptStaticChild = &VGA3BitI::interrupt;
2223
}
2324

2425
bool init(const Mode &mode, const int RPin, const int GPin, const int BPin, const int hsyncPin, const int vsyncPin, const int clockPin = -1)
@@ -29,7 +30,7 @@ class VGA3BitI : public VGA, public GraphicsR1G1B1A1
2930
BPin,
3031
-1, -1, -1,
3132
hsyncPin, vsyncPin
32-
};
33+
};
3334
return VGA::init(mode, pinMap, 8, clockPin);
3435
}
3536

@@ -87,53 +88,61 @@ class VGA3BitI : public VGA, public GraphicsR1G1B1A1
8788
return true;
8889
};
8990

90-
void interrupt()
91+
static void interrupt(void *arg);
92+
93+
static void interruptPixelLine(int y, unsigned long *pixels, unsigned long syncBits, void *arg);
94+
};
95+
96+
97+
void IRAM_ATTR VGA3BitI::interrupt(void *arg)
98+
{
99+
VGA3BitI * staticthis = (VGA3BitI *)arg;
100+
101+
unsigned long *signal = (unsigned long *)staticthis->dmaBufferDescriptors[staticthis->dmaBufferDescriptorActive].buffer();
102+
unsigned long *pixels = &((unsigned long *)staticthis->dmaBufferDescriptors[staticthis->dmaBufferDescriptorActive].buffer())[(staticthis->mode.hSync + staticthis->mode.hBack) / 4];
103+
unsigned long base, baseh;
104+
if (staticthis->currentLine >= staticthis->mode.vFront && staticthis->currentLine < staticthis->mode.vFront + staticthis->mode.vSync)
91105
{
92-
unsigned long *signal = (unsigned long *)dmaBufferDescriptors[dmaBufferDescriptorActive].buffer();
93-
unsigned long *pixels = &((unsigned long *)dmaBufferDescriptors[dmaBufferDescriptorActive].buffer())[(mode.hSync + mode.hBack) / 4];
94-
unsigned long base, baseh;
95-
if (currentLine >= mode.vFront && currentLine < mode.vFront + mode.vSync)
96-
{
97-
baseh = syncBits(true, true);
98-
base = syncBits(false, true);
99-
}
100-
else
101-
{
102-
baseh = syncBits(true, false);
103-
base = syncBits(false, false);
104-
}
105-
for (int i = 0; i < mode.hSync / 4; i++)
106-
signal[i] = baseh;
107-
for (int i = mode.hSync / 4; i < (mode.hSync + mode.hBack) / 4; i++)
108-
signal[i] = base;
109-
110-
int y = (currentLine - mode.vFront - mode.vSync - mode.vBack) / mode.vDiv;
111-
if (y >= 0 && y < mode.vRes)
112-
interruptPixelLine(y, pixels, base);
113-
else
114-
for (int i = 0; i < mode.hRes / 4; i++)
115-
{
116-
pixels[i] = base;
117-
}
118-
for (int i = 0; i < mode.hFront / 4; i++)
119-
signal[i + (mode.hSync + mode.hBack + mode.hRes) / 4] = base;
120-
currentLine = (currentLine + 1) % totalLines;
121-
dmaBufferDescriptorActive = (dmaBufferDescriptorActive + 1) % dmaBufferDescriptorCount;
122-
if (currentLine == 0)
123-
vSync();
106+
baseh = (staticthis->hsyncBit | staticthis->vsyncBit) * 0x1010101;
107+
base = (staticthis->hsyncBitI | staticthis->vsyncBit) * 0x1010101;
124108
}
125-
126-
void interruptPixelLine(int y, unsigned long *pixels, unsigned long syncBits)
109+
else
127110
{
128-
unsigned char *line = frontBuffer[y];
129-
int j = 0;
130-
for (int i = 0; i < mode.hRes / 4; i++)
111+
baseh = (staticthis->hsyncBit | staticthis->vsyncBitI) * 0x1010101;
112+
base = (staticthis->hsyncBitI | staticthis->vsyncBitI) * 0x1010101;
113+
}
114+
for (int i = 0; i < staticthis->mode.hSync / 4; i++)
115+
signal[i] = baseh;
116+
for (int i = staticthis->mode.hSync / 4; i < (staticthis->mode.hSync + staticthis->mode.hBack) / 4; i++)
117+
signal[i] = base;
118+
119+
int y = (staticthis->currentLine - staticthis->mode.vFront - staticthis->mode.vSync - staticthis->mode.vBack) / staticthis->mode.vDiv;
120+
if (y >= 0 && y < staticthis->mode.vRes)
121+
staticthis->interruptPixelLine(y, pixels, base, arg);
122+
else
123+
for (int i = 0; i < staticthis->mode.hRes / 4; i++)
131124
{
132-
int p0 = (line[j] >> 0) & 7;
133-
int p1 = (line[j++] >> 4) & 7;
134-
int p2 = (line[j] >> 0) & 7;
135-
int p3 = (line[j++] >> 4) & 7;
136-
pixels[i] = syncBits | (p2 << 0) | (p3 << 8) | (p0 << 16) | (p1 << 24);
125+
pixels[i] = base;
137126
}
127+
for (int i = 0; i < staticthis->mode.hFront / 4; i++)
128+
signal[i + (staticthis->mode.hSync + staticthis->mode.hBack + staticthis->mode.hRes) / 4] = base;
129+
staticthis->currentLine = (staticthis->currentLine + 1) % staticthis->totalLines;
130+
staticthis->dmaBufferDescriptorActive = (staticthis->dmaBufferDescriptorActive + 1) % staticthis->dmaBufferDescriptorCount;
131+
if (staticthis->currentLine == 0)
132+
staticthis->vSyncPassed = true;
133+
}
134+
135+
void IRAM_ATTR VGA3BitI::interruptPixelLine(int y, unsigned long *pixels, unsigned long syncBits, void *arg)
136+
{
137+
VGA3BitI * staticthis = (VGA3BitI *)arg;
138+
unsigned char *line = staticthis->frontBuffer[y];
139+
int j = 0;
140+
for (int i = 0; i < staticthis->mode.hRes / 4; i++)
141+
{
142+
int p0 = (line[j] >> 0) & 7;
143+
int p1 = (line[j++] >> 4) & 7;
144+
int p2 = (line[j] >> 0) & 7;
145+
int p3 = (line[j++] >> 4) & 7;
146+
pixels[i] = syncBits | (p2 << 0) | (p3 << 8) | (p0 << 16) | (p1 << 24);
138147
}
139-
};
148+
}

0 commit comments

Comments
 (0)