Add Library
This commit is contained in:
parent
e365b9dbd9
commit
3c47103b39
318 changed files with 56465 additions and 0 deletions
122
libraries/bitluni_ESP32Lib/src/VGA/Mode.h
Normal file
122
libraries/bitluni_ESP32Lib/src/VGA/Mode.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
Author: bitluni 2019
|
||||
License:
|
||||
Creative Commons Attribution ShareAlike 4.0
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
For further details check out:
|
||||
https://youtube.com/bitlunislab
|
||||
https://github.com/bitluni
|
||||
http://bitluni.net
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
class Mode
|
||||
{
|
||||
public:
|
||||
int hFront;
|
||||
int hSync;
|
||||
int hBack;
|
||||
int hRes;
|
||||
int vFront;
|
||||
int vSync;
|
||||
int vBack;
|
||||
int vRes;
|
||||
int vDiv;
|
||||
unsigned long pixelClock;
|
||||
int hSyncPolarity;
|
||||
int vSyncPolarity;
|
||||
float aspect;
|
||||
int activeLineCount;
|
||||
Mode(
|
||||
const int hFront = 0,
|
||||
const int hSync = 0,
|
||||
const int hBack = 0,
|
||||
const int hRes = 0,
|
||||
const int vFront = 0,
|
||||
const int vSync = 0,
|
||||
const int vBack = 0,
|
||||
const int vRes = 0,
|
||||
const int vDiv = 1,
|
||||
const unsigned long pixelClock = 0,
|
||||
const int hSyncPolarity = 1,
|
||||
const int vSyncPolarity = 1,
|
||||
const float aspect = 1.f)
|
||||
: hFront(hFront),
|
||||
hSync(hSync),
|
||||
hBack(hBack),
|
||||
hRes(hRes),
|
||||
vFront(vFront),
|
||||
vSync(vSync),
|
||||
vBack(vBack),
|
||||
vRes(vRes),
|
||||
vDiv(vDiv),
|
||||
pixelClock(pixelClock),
|
||||
hSyncPolarity(hSyncPolarity),
|
||||
vSyncPolarity(vSyncPolarity),
|
||||
aspect(aspect),
|
||||
activeLineCount(vRes / vDiv)
|
||||
{
|
||||
}
|
||||
|
||||
int maxXRes() const
|
||||
{
|
||||
return (int(hRes * 19673499. / pixelClock) & 0xfffffffe);
|
||||
}
|
||||
|
||||
int linesPerField() const
|
||||
{
|
||||
return vFront + vSync + vBack + vRes;
|
||||
}
|
||||
|
||||
int pixelsPerLine() const
|
||||
{
|
||||
return hFront + hSync + hBack + hRes;
|
||||
}
|
||||
|
||||
Mode custom(int xres, int yres, int fixedYDivider = 0) const
|
||||
{
|
||||
xres = (xres + 3) & 0xfffffffc;
|
||||
float f = float(xres) / hRes;
|
||||
int hs = int(hSync * f + 3) & 0xfffffffc;
|
||||
int hb = int((hSync + hBack - hs / f) * f + 3) & 0xfffffffc;
|
||||
int hr = xres;
|
||||
int hf = int((pixelsPerLine() - (hs + hb + hr) / f) * f + 3) & 0xfffffffc;
|
||||
|
||||
int vd = fixedYDivider ? fixedYDivider : (vRes / yres);
|
||||
int vr = yres * vd;
|
||||
int vf = vFront + vRes / 2 - vr / 2;
|
||||
int vb = vBack + vRes / 2 - (vr - vr / 2);
|
||||
long pc = long(pixelClock * f);
|
||||
return Mode(hf, hs, hb, hr, vf, vSync, vb, vr, vd, pc, hSyncPolarity, vSyncPolarity);
|
||||
}
|
||||
|
||||
template<class Output>
|
||||
void print(Output &output) const
|
||||
{
|
||||
output.print("hFront: ");
|
||||
output.println(hFront);
|
||||
output.print("hSync: ");
|
||||
output.println(hSync);
|
||||
output.print("hBack: ");
|
||||
output.println(hBack);
|
||||
output.print("hRes: ");
|
||||
output.println(hRes);
|
||||
output.print("vFront: ");
|
||||
output.println(vFront);
|
||||
output.print("vSync: ");
|
||||
output.println(vSync);
|
||||
output.print("vBack: ");
|
||||
output.println(vBack);
|
||||
output.print("vRes: ");
|
||||
output.println(vRes);
|
||||
output.print("vDiv: ");
|
||||
output.println(vDiv);
|
||||
output.print("pixelClock: ");
|
||||
output.println(pixelClock);
|
||||
output.print("hSyncPolarity: ");
|
||||
output.println(hSyncPolarity);
|
||||
output.print("vSyncPolarity: ");
|
||||
output.println(vSyncPolarity);
|
||||
}
|
||||
};
|
102
libraries/bitluni_ESP32Lib/src/VGA/PinConfig.h
Normal file
102
libraries/bitluni_ESP32Lib/src/VGA/PinConfig.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
Author: bitluni 2019
|
||||
License:
|
||||
Creative Commons Attribution ShareAlike 4.0
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
For further details check out:
|
||||
https://youtube.com/bitlunislab
|
||||
https://github.com/bitluni
|
||||
http://bitluni.net
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
class PinConfig
|
||||
{
|
||||
public:
|
||||
int r0, r1, r2, r3, r4;
|
||||
int g0, g1, g2, g3, g4;
|
||||
int b0, b1, b2, b3;
|
||||
int hSync, vSync, clock;
|
||||
PinConfig(
|
||||
const int r0 = -1,
|
||||
const int r1 = -1,
|
||||
const int r2 = -1,
|
||||
const int r3 = -1,
|
||||
const int r4 = -1,
|
||||
const int g0 = -1,
|
||||
const int g1 = -1,
|
||||
const int g2 = -1,
|
||||
const int g3 = -1,
|
||||
const int g4 = -1,
|
||||
const int b0 = -1,
|
||||
const int b1 = -1,
|
||||
const int b2 = -1,
|
||||
const int b3 = -1,
|
||||
const int hSync = -1,
|
||||
const int vSync = -1,
|
||||
const int clock = -1)
|
||||
: r0(r0),
|
||||
r1(r1),
|
||||
r2(r2),
|
||||
r3(r3),
|
||||
r4(r4),
|
||||
g0(g0),
|
||||
g1(g1),
|
||||
g2(g2),
|
||||
g3(g3),
|
||||
g4(g4),
|
||||
b0(b0),
|
||||
b1(b1),
|
||||
b2(b2),
|
||||
b3(b3),
|
||||
hSync(hSync),
|
||||
vSync(vSync),
|
||||
clock(clock)
|
||||
{
|
||||
}
|
||||
|
||||
void fill3Bit(int *pins) const
|
||||
{
|
||||
pins[0] = r4;
|
||||
pins[1] = g4;
|
||||
pins[2] = b3;
|
||||
pins[3] = -1;
|
||||
pins[4] = -1;
|
||||
pins[5] = -1;
|
||||
pins[6] = hSync;
|
||||
pins[7] = vSync;
|
||||
}
|
||||
|
||||
void fill6Bit(int *pins) const
|
||||
{
|
||||
pins[0] = r3;
|
||||
pins[1] = r4;
|
||||
pins[2] = g3;
|
||||
pins[3] = g4;
|
||||
pins[4] = b2;
|
||||
pins[5] = b3;
|
||||
pins[6] = hSync;
|
||||
pins[7] = vSync;
|
||||
}
|
||||
|
||||
void fill14Bit(int *pins) const
|
||||
{
|
||||
pins[0] = r0;
|
||||
pins[1] = r1;
|
||||
pins[2] = r2;
|
||||
pins[3] = r3;
|
||||
pins[4] = r4;
|
||||
pins[5] = g0;
|
||||
pins[6] = g1;
|
||||
pins[7] = g2;
|
||||
pins[8] = g3;
|
||||
pins[9] = g4;
|
||||
pins[10] = b0;
|
||||
pins[11] = b1;
|
||||
pins[12] = b2;
|
||||
pins[13] = b3;
|
||||
pins[14] = hSync;
|
||||
pins[15] = vSync;
|
||||
}
|
||||
};
|
225
libraries/bitluni_ESP32Lib/src/VGA/VGA.cpp
Normal file
225
libraries/bitluni_ESP32Lib/src/VGA/VGA.cpp
Normal file
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
Author: bitluni 2019
|
||||
License:
|
||||
Creative Commons Attribution ShareAlike 4.0
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
For further details check out:
|
||||
https://youtube.com/bitlunislab
|
||||
https://github.com/bitluni
|
||||
http://bitluni.net
|
||||
*/
|
||||
#include "VGA.h"
|
||||
|
||||
//hfront hsync hback pixels vfront vsync vback lines divy pixelclock hpolaritynegative vpolaritynegative
|
||||
const Mode VGA::MODE320x480(8, 48, 24, 320, 11, 2, 31, 480, 1, 12587500, 1, 1);
|
||||
const Mode VGA::MODE320x240(8, 48, 24, 320, 11, 2, 31, 480, 2, 12587500, 1, 1);
|
||||
const Mode VGA::MODE320x400(8, 48, 24, 320, 12, 2, 35, 400, 1, 12587500, 1, 0);
|
||||
const Mode VGA::MODE320x200(8, 48, 24, 320, 12, 2, 35, 400, 2, 12587500, 1, 0);
|
||||
const Mode VGA::MODE360x400(8, 54, 28, 360, 11, 2, 32, 400, 1, 14161000, 1, 0);
|
||||
const Mode VGA::MODE360x200(8, 54, 28, 360, 11, 2, 32, 400, 2, 14161000, 1, 0);
|
||||
const Mode VGA::MODE360x350(8, 54, 28, 360, 11, 2, 32, 350, 1, 14161000, 1, 1);
|
||||
const Mode VGA::MODE360x175 (8, 54, 28, 360, 11, 2, 32, 350, 2, 14161000, 1, 1);
|
||||
|
||||
const Mode VGA::MODE320x350 (8, 48, 24, 320, 37, 2, 60, 350, 1, 12587500, 0, 1);
|
||||
const Mode VGA::MODE320x175(8, 48, 24, 320, 37, 2, 60, 350, 2, 12587500, 0, 1);
|
||||
|
||||
const Mode VGA::MODE400x300(12, 36, 64, 400, 1, 2, 22, 600, 2, 18000000, 0, 0);
|
||||
const Mode VGA::MODE400x150(12, 36, 64, 400, 1, 2, 22, 600, 4, 18000000, 0, 0);
|
||||
const Mode VGA::MODE400x100(12, 36, 64, 400, 1, 2, 22, 600, 6, 18000000, 0, 0);
|
||||
const Mode VGA::MODE200x150(6, 18, 32, 200, 1, 2, 22, 600, 4, 9000000, 0, 0);
|
||||
//const Mode VGA::MODE200x150(10, 32, 22, 200, 1, 4, 23, 600, 4, 10000000, 0, 0); //60Hz version
|
||||
|
||||
//500 pixels horizontal it's based on 640x480
|
||||
const Mode VGA::MODE500x480(12, 76, 38, 500, 11, 2, 31, 480, 1, 19667968, 1, 1);
|
||||
const Mode VGA::MODE500x240(12, 76, 38, 500, 11, 2, 31, 480, 2, 19667968, 1, 1);
|
||||
|
||||
//base modes for custom mode calculations
|
||||
const Mode VGA::MODE1280x1024(48, 112, 248, 1280, 1, 3, 38, 1024, 1, 108000000, 0, 0);
|
||||
const Mode VGA::MODE1280x960(80, 136, 216, 1280, 1, 3, 30, 960, 1, 101200000, 1, 0);
|
||||
const Mode VGA::MODE1280x800(64, 136, 200, 1280, 1, 3, 24, 800, 1, 83640000, 1, 0);
|
||||
const Mode VGA::MODE1024x768(24, 136, 160, 1024, 3, 6, 29, 768, 1, 65000000, 1, 1);
|
||||
const Mode VGA::MODE800x600(24, 72, 128, 800, 1, 2, 22, 600, 1, 36000000, 0, 0);
|
||||
const Mode VGA::MODE720x400(16, 108, 56, 720, 11, 2, 32, 400, 1, 28322000, 1, 0);
|
||||
const Mode VGA::MODE720x350(16, 108, 56, 720, 11, 2, 32, 350, 1, 28322000, 1, 1);
|
||||
const Mode VGA::MODE640x480(16, 96, 48, 640, 11, 2, 31, 480, 1, 25175000, 1, 1);
|
||||
const Mode VGA::MODE640x400(16, 96, 48, 640, 12, 2, 35, 400, 1, 25175000, 1, 0);
|
||||
const Mode VGA::MODE640x350(16, 96, 48, 640, 37, 2, 60, 350, 1, 25175000, 0, 1);
|
||||
|
||||
const PinConfig VGA::VGAv01(2, 4, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 27, 32, 33, -1);
|
||||
const PinConfig VGA::VGABlackEdition(2, 4, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 27, 32, 33, -1);
|
||||
const PinConfig VGA::VGAWhiteEdition(5, 14, 13, 15, 2, 19, 18, 17, 4, 16, 27, 22, 12, 21, 32, 33, -1);
|
||||
const PinConfig VGA::PicoVGA(-1, -1, -1, 18, 5, -1, -1, -1, 14, 4, -1, -1, 27, 15, 32, 33, -1);
|
||||
|
||||
VGA::VGA(const int i2sIndex)
|
||||
: I2S(i2sIndex)
|
||||
{
|
||||
lineBufferCount = 8;
|
||||
dmaBufferDescriptors = 0;
|
||||
}
|
||||
|
||||
bool VGA::init(const Mode &mode, const int *pinMap, const int bitCount, const int clockPin)
|
||||
{
|
||||
this->mode = mode;
|
||||
int xres = mode.hRes;
|
||||
int yres = mode.vRes / mode.vDiv;
|
||||
initSyncBits();
|
||||
propagateResolution(xres, yres);
|
||||
this->vsyncPin = vsyncPin;
|
||||
this->hsyncPin = hsyncPin;
|
||||
totalLines = mode.linesPerField();
|
||||
allocateLineBuffers();
|
||||
currentLine = 0;
|
||||
vSyncPassed = false;
|
||||
initParallelOutputMode(pinMap, mode.pixelClock, bitCount, clockPin);
|
||||
startTX();
|
||||
return true;
|
||||
}
|
||||
|
||||
void VGA::setLineBufferCount(int lineBufferCount)
|
||||
{
|
||||
this->lineBufferCount = lineBufferCount;
|
||||
}
|
||||
|
||||
void VGA::allocateLineBuffers()
|
||||
{
|
||||
allocateLineBuffers(lineBufferCount);
|
||||
}
|
||||
|
||||
/// simple ringbuffer of blocks of size bytes each
|
||||
void VGA::allocateLineBuffers(const int lines)
|
||||
{
|
||||
dmaBufferDescriptorCount = lines;
|
||||
dmaBufferDescriptors = DMABufferDescriptor::allocateDescriptors(dmaBufferDescriptorCount);
|
||||
int bytes = (mode.hFront + mode.hSync + mode.hBack + mode.hRes) * bytesPerSample();
|
||||
for (int i = 0; i < dmaBufferDescriptorCount; i++)
|
||||
{
|
||||
dmaBufferDescriptors[i].setBuffer(DMABufferDescriptor::allocateBuffer(bytes, true), bytes); //front porch + hsync + back porch + pixels
|
||||
if (i)
|
||||
dmaBufferDescriptors[i - 1].next(dmaBufferDescriptors[i]);
|
||||
}
|
||||
dmaBufferDescriptors[dmaBufferDescriptorCount - 1].next(dmaBufferDescriptors[0]);
|
||||
}
|
||||
|
||||
///complete ringbuffer from frame
|
||||
void VGA::allocateLineBuffers(void **frameBuffer)
|
||||
{
|
||||
dmaBufferDescriptorCount = totalLines * 2;
|
||||
int inactiveSamples = (mode.hFront + mode.hSync + mode.hBack + 3) & 0xfffffffc;
|
||||
vSyncInactiveBuffer = DMABufferDescriptor::allocateBuffer(inactiveSamples * bytesPerSample(), true);
|
||||
vSyncActiveBuffer = DMABufferDescriptor::allocateBuffer(mode.hRes * bytesPerSample(), true);
|
||||
inactiveBuffer = DMABufferDescriptor::allocateBuffer(inactiveSamples * bytesPerSample(), true);
|
||||
blankActiveBuffer = DMABufferDescriptor::allocateBuffer(mode.hRes * bytesPerSample(), true);
|
||||
if(bytesPerSample() == 1)
|
||||
{
|
||||
for (int i = 0; i < inactiveSamples; i++)
|
||||
{
|
||||
if (i >= mode.hFront && i < mode.hFront + mode.hSync)
|
||||
{
|
||||
((unsigned char *)vSyncInactiveBuffer)[i ^ 2] = hsyncBit | vsyncBit;
|
||||
((unsigned char *)inactiveBuffer)[i ^ 2] = hsyncBit | vsyncBitI;
|
||||
}
|
||||
else
|
||||
{
|
||||
((unsigned char *)vSyncInactiveBuffer)[i ^ 2] = hsyncBitI | vsyncBit;
|
||||
((unsigned char *)inactiveBuffer)[i ^ 2] = hsyncBitI | vsyncBitI;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < mode.hRes; i++)
|
||||
{
|
||||
((unsigned char *)vSyncActiveBuffer)[i ^ 2] = hsyncBitI | vsyncBit;
|
||||
((unsigned char *)blankActiveBuffer)[i ^ 2] = hsyncBitI | vsyncBitI;
|
||||
}
|
||||
}
|
||||
else if(bytesPerSample() == 2)
|
||||
{
|
||||
for (int i = 0; i < inactiveSamples; i++)
|
||||
{
|
||||
if (i >= mode.hFront && i < mode.hFront + mode.hSync)
|
||||
{
|
||||
((unsigned short *)vSyncInactiveBuffer)[i ^ 1] = hsyncBit | vsyncBit;
|
||||
((unsigned short *)inactiveBuffer)[i ^ 1] = hsyncBit | vsyncBitI;
|
||||
}
|
||||
else
|
||||
{
|
||||
((unsigned short *)vSyncInactiveBuffer)[i ^ 1] = hsyncBitI | vsyncBit;
|
||||
((unsigned short *)inactiveBuffer)[i ^ 1] = hsyncBitI | vsyncBitI;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < mode.hRes; i++)
|
||||
{
|
||||
((unsigned short *)vSyncActiveBuffer)[i ^ 1] = hsyncBitI | vsyncBit;
|
||||
((unsigned short *)blankActiveBuffer)[i ^ 1] = hsyncBitI | vsyncBitI;
|
||||
}
|
||||
}
|
||||
|
||||
dmaBufferDescriptors = DMABufferDescriptor::allocateDescriptors(dmaBufferDescriptorCount);
|
||||
for (int i = 0; i < dmaBufferDescriptorCount; i++)
|
||||
dmaBufferDescriptors[i].next(dmaBufferDescriptors[(i + 1) % dmaBufferDescriptorCount]);
|
||||
int d = 0;
|
||||
for (int i = 0; i < mode.vFront; i++)
|
||||
{
|
||||
dmaBufferDescriptors[d++].setBuffer(inactiveBuffer, inactiveSamples * bytesPerSample());
|
||||
dmaBufferDescriptors[d++].setBuffer(blankActiveBuffer, mode.hRes * bytesPerSample());
|
||||
}
|
||||
for (int i = 0; i < mode.vSync; i++)
|
||||
{
|
||||
dmaBufferDescriptors[d++].setBuffer(vSyncInactiveBuffer, inactiveSamples * bytesPerSample());
|
||||
dmaBufferDescriptors[d++].setBuffer(vSyncActiveBuffer, mode.hRes * bytesPerSample());
|
||||
}
|
||||
for (int i = 0; i < mode.vBack; i++)
|
||||
{
|
||||
dmaBufferDescriptors[d++].setBuffer(inactiveBuffer, inactiveSamples * bytesPerSample());
|
||||
dmaBufferDescriptors[d++].setBuffer(blankActiveBuffer, mode.hRes * bytesPerSample());
|
||||
}
|
||||
for (int i = 0; i < mode.vRes; i++)
|
||||
{
|
||||
dmaBufferDescriptors[d++].setBuffer(inactiveBuffer, inactiveSamples * bytesPerSample());
|
||||
dmaBufferDescriptors[d++].setBuffer(frameBuffer[i / mode.vDiv], mode.hRes * bytesPerSample());
|
||||
}
|
||||
}
|
||||
|
||||
void VGA::vSync()
|
||||
{
|
||||
vSyncPassed = true;
|
||||
}
|
||||
|
||||
void VGA::interrupt()
|
||||
{
|
||||
unsigned long *signal = (unsigned long *)dmaBufferDescriptors[dmaBufferDescriptorActive].buffer();
|
||||
unsigned long *pixels = &((unsigned long *)dmaBufferDescriptors[dmaBufferDescriptorActive].buffer())[(mode.hSync + mode.hBack) / 2];
|
||||
unsigned long base, baseh;
|
||||
if (currentLine >= mode.vFront && currentLine < mode.vFront + mode.vSync)
|
||||
{
|
||||
baseh = (vsyncBit | hsyncBit) | ((vsyncBit | hsyncBit) << 16);
|
||||
base = (vsyncBit | hsyncBitI) | ((vsyncBit | hsyncBitI) << 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
baseh = (vsyncBitI | hsyncBit) | ((vsyncBitI | hsyncBit) << 16);
|
||||
base = (vsyncBitI | hsyncBitI) | ((vsyncBitI | hsyncBitI) << 16);
|
||||
}
|
||||
for (int i = 0; i < mode.hSync / 2; i++)
|
||||
signal[i] = baseh;
|
||||
for (int i = mode.hSync / 2; i < (mode.hSync + mode.hBack) / 2; i++)
|
||||
signal[i] = base;
|
||||
|
||||
int y = (currentLine - mode.vFront - mode.vSync - mode.vBack) / mode.vDiv;
|
||||
if (y >= 0 && y < mode.vRes)
|
||||
interruptPixelLine(y, pixels, base);
|
||||
else
|
||||
for (int i = 0; i < mode.hRes / 2; i++)
|
||||
{
|
||||
pixels[i] = base | (base << 16);
|
||||
}
|
||||
for (int i = 0; i < mode.hFront / 2; i++)
|
||||
signal[i + (mode.hSync + mode.hBack + mode.hRes) / 2] = base;
|
||||
currentLine = (currentLine + 1) % totalLines;
|
||||
dmaBufferDescriptorActive = (dmaBufferDescriptorActive + 1) % dmaBufferDescriptorCount;
|
||||
if (currentLine == 0)
|
||||
vSync();
|
||||
}
|
||||
|
||||
void VGA::interruptPixelLine(int y, unsigned long *pixels, unsigned long syncBits)
|
||||
{
|
||||
}
|
99
libraries/bitluni_ESP32Lib/src/VGA/VGA.h
Normal file
99
libraries/bitluni_ESP32Lib/src/VGA/VGA.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
Author: bitluni 2019
|
||||
License:
|
||||
Creative Commons Attribution ShareAlike 4.0
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
For further details check out:
|
||||
https://youtube.com/bitlunislab
|
||||
https://github.com/bitluni
|
||||
http://bitluni.net
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../I2S/I2S.h"
|
||||
#include "Mode.h"
|
||||
#include "PinConfig.h"
|
||||
|
||||
class VGA : public I2S
|
||||
{
|
||||
public:
|
||||
VGA(const int i2sIndex = 0);
|
||||
void setLineBufferCount(int lineBufferCount);
|
||||
bool init(const Mode &mode, const int *pinMap, const int bitCount, const int clockPin = -1);
|
||||
virtual bool init(const Mode &mode, const PinConfig &pinConfig) = 0;
|
||||
|
||||
static const Mode MODE320x480;
|
||||
static const Mode MODE320x240;
|
||||
static const Mode MODE320x120;
|
||||
static const Mode MODE320x400;
|
||||
static const Mode MODE320x200;
|
||||
static const Mode MODE360x400;
|
||||
static const Mode MODE360x200;
|
||||
static const Mode MODE360x350;
|
||||
static const Mode MODE360x175;
|
||||
|
||||
static const Mode MODE320x350;
|
||||
static const Mode MODE320x175;
|
||||
|
||||
static const Mode MODE400x300;
|
||||
static const Mode MODE400x150;
|
||||
static const Mode MODE400x100;
|
||||
static const Mode MODE200x150;
|
||||
|
||||
static const Mode MODE500x480;
|
||||
static const Mode MODE500x240;
|
||||
|
||||
static const Mode MODE1280x1024;
|
||||
static const Mode MODE1280x960;
|
||||
static const Mode MODE1280x800;
|
||||
static const Mode MODE1024x768;
|
||||
static const Mode MODE800x600;
|
||||
static const Mode MODE720x400;
|
||||
static const Mode MODE720x350;
|
||||
static const Mode MODE640x480;
|
||||
static const Mode MODE640x400;
|
||||
static const Mode MODE640x350;
|
||||
|
||||
static const PinConfig VGAv01;
|
||||
static const PinConfig VGABlackEdition;
|
||||
static const PinConfig VGAWhiteEdition;
|
||||
static const PinConfig PicoVGA;
|
||||
|
||||
|
||||
Mode mode;
|
||||
|
||||
virtual int bytesPerSample() const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
virtual void initSyncBits() = 0;
|
||||
virtual long syncBits(bool h, bool v) = 0;
|
||||
|
||||
int lineBufferCount;
|
||||
int vsyncPin;
|
||||
int hsyncPin;
|
||||
int currentLine;
|
||||
long vsyncBit;
|
||||
long hsyncBit;
|
||||
long vsyncBitI;
|
||||
long hsyncBitI;
|
||||
|
||||
int totalLines;
|
||||
volatile bool vSyncPassed;
|
||||
|
||||
void *vSyncInactiveBuffer;
|
||||
void *vSyncActiveBuffer;
|
||||
void *inactiveBuffer;
|
||||
void *blankActiveBuffer;
|
||||
|
||||
void allocateLineBuffers(const int lines);
|
||||
virtual void allocateLineBuffers();
|
||||
virtual void allocateLineBuffers(void **frameBuffer);
|
||||
virtual void propagateResolution(const int xres, const int yres) = 0;
|
||||
|
||||
protected:
|
||||
virtual void interrupt();
|
||||
virtual void vSync();
|
||||
virtual void interruptPixelLine(int y, unsigned long *pixels, unsigned long syncBits);
|
||||
};
|
126
libraries/bitluni_ESP32Lib/src/VGA/VGA14Bit.h
Normal file
126
libraries/bitluni_ESP32Lib/src/VGA/VGA14Bit.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
Author: bitluni 2019
|
||||
License:
|
||||
Creative Commons Attribution ShareAlike 4.0
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
For further details check out:
|
||||
https://youtube.com/bitlunislab
|
||||
https://github.com/bitluni
|
||||
http://bitluni.net
|
||||
*/
|
||||
#pragma once
|
||||
#include "VGA.h"
|
||||
#include "../Graphics/GraphicsR5G5B4S2Swapped.h"
|
||||
|
||||
class VGA14Bit : public VGA, public GraphicsR5G5B4S2Swapped
|
||||
{
|
||||
public:
|
||||
VGA14Bit(const int i2sIndex = 1)
|
||||
: VGA(i2sIndex)
|
||||
{
|
||||
}
|
||||
|
||||
bool init(Mode &mode,
|
||||
const int R0Pin, const int R1Pin, const int R2Pin, const int R3Pin, const int R4Pin,
|
||||
const int G0Pin, const int G1Pin, const int G2Pin, const int G3Pin, const int G4Pin,
|
||||
const int B0Pin, const int B1Pin, const int B2Pin, const int B3Pin,
|
||||
const int hsyncPin, const int vsyncPin, const int clockPin = -1)
|
||||
{
|
||||
int pinMap[16] = {
|
||||
R0Pin, R1Pin, R2Pin, R3Pin, R4Pin,
|
||||
G0Pin, G1Pin, G2Pin, G3Pin, G4Pin,
|
||||
B0Pin, B1Pin, B2Pin, B3Pin,
|
||||
hsyncPin, vsyncPin
|
||||
};
|
||||
|
||||
return VGA::init(mode, pinMap, 16, clockPin);
|
||||
}
|
||||
|
||||
bool init(const Mode &mode, const int *redPins, const int *greenPins, const int *bluePins, const int hsyncPin, const int vsyncPin, const int clockPin = -1)
|
||||
{
|
||||
int pinMap[16];
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
pinMap[i] = redPins[i];
|
||||
pinMap[i + 5] = greenPins[i];
|
||||
if (i < 4)
|
||||
pinMap[i + 10] = bluePins[i];
|
||||
}
|
||||
pinMap[14] = hsyncPin;
|
||||
pinMap[15] = vsyncPin;
|
||||
return VGA::init(mode, pinMap, 16, clockPin);
|
||||
}
|
||||
|
||||
bool init(const Mode &mode, const PinConfig &pinConfig)
|
||||
{
|
||||
int pins[16];
|
||||
pinConfig.fill14Bit(pins);
|
||||
return VGA::init(mode, pins, 16, pinConfig.clock);
|
||||
}
|
||||
|
||||
virtual void initSyncBits()
|
||||
{
|
||||
hsyncBitI = mode.hSyncPolarity ? 0x4000 : 0;
|
||||
vsyncBitI = mode.vSyncPolarity ? 0x8000 : 0;
|
||||
hsyncBit = hsyncBitI ^ 0x4000;
|
||||
vsyncBit = vsyncBitI ^ 0x8000;
|
||||
SBits = hsyncBitI | vsyncBitI;
|
||||
}
|
||||
|
||||
virtual long syncBits(bool hSync, bool vSync)
|
||||
{
|
||||
return ((hSync ? hsyncBit : hsyncBitI) | (vSync ? vsyncBit : vsyncBitI)) * 0x10001;
|
||||
}
|
||||
|
||||
virtual int bytesPerSample() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
virtual float pixelAspect() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void propagateResolution(const int xres, const int yres)
|
||||
{
|
||||
setResolution(xres, yres);
|
||||
}
|
||||
|
||||
virtual Color **allocateFrameBuffer()
|
||||
{
|
||||
return (Color **)DMABufferDescriptor::allocateDMABufferArray(yres, mode.hRes * bytesPerSample(), true, syncBits(false, false));
|
||||
}
|
||||
|
||||
virtual void allocateLineBuffers()
|
||||
{
|
||||
VGA::allocateLineBuffers((void **)frameBuffers[0]);
|
||||
}
|
||||
|
||||
virtual void show(bool vSync = false)
|
||||
{
|
||||
if (!frameBufferCount)
|
||||
return;
|
||||
if (vSync)
|
||||
{
|
||||
//TODO read the I2S docs to find out
|
||||
}
|
||||
Graphics::show(vSync);
|
||||
if(dmaBufferDescriptors)
|
||||
for (int i = 0; i < yres * mode.vDiv; i++)
|
||||
dmaBufferDescriptors[(mode.vFront + mode.vSync + mode.vBack + i) * 2 + 1].setBuffer(frontBuffer[i / mode.vDiv], mode.hRes * bytesPerSample());
|
||||
}
|
||||
|
||||
virtual void scroll(int dy, Color color)
|
||||
{
|
||||
Graphics::scroll(dy, color);
|
||||
if (frameBufferCount == 1)
|
||||
show();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void interrupt()
|
||||
{
|
||||
}
|
||||
};
|
117
libraries/bitluni_ESP32Lib/src/VGA/VGA14BitI.h
Normal file
117
libraries/bitluni_ESP32Lib/src/VGA/VGA14BitI.h
Normal file
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
Author: bitluni 2019
|
||||
License:
|
||||
Creative Commons Attribution ShareAlike 4.0
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
For further details check out:
|
||||
https://youtube.com/bitlunislab
|
||||
https://github.com/bitluni
|
||||
http://bitluni.net
|
||||
*/
|
||||
#pragma once
|
||||
#include "VGA.h"
|
||||
#include "../Graphics/GraphicsR5G5B4A2.h"
|
||||
|
||||
class VGA14BitI : public VGA, public GraphicsR5G5B4A2
|
||||
{
|
||||
public:
|
||||
VGA14BitI(const int i2sIndex = 1)
|
||||
: VGA(i2sIndex)
|
||||
{
|
||||
}
|
||||
|
||||
bool init(const Mode &mode,
|
||||
const int R0Pin, const int R1Pin, const int R2Pin, const int R3Pin, const int R4Pin,
|
||||
const int G0Pin, const int G1Pin, const int G2Pin, const int G3Pin, const int G4Pin,
|
||||
const int B0Pin, const int B1Pin, const int B2Pin, const int B3Pin,
|
||||
const int hsyncPin, const int vsyncPin, const int clockPin = -1)
|
||||
{
|
||||
int pinMap[16] = {
|
||||
R0Pin, R1Pin, R2Pin, R3Pin, R4Pin,
|
||||
G0Pin, G1Pin, G2Pin, G3Pin, G4Pin,
|
||||
B0Pin, B1Pin, B2Pin, B3Pin,
|
||||
hsyncPin, vsyncPin
|
||||
};
|
||||
return VGA::init(mode, pinMap, 16, clockPin);
|
||||
}
|
||||
|
||||
bool init(const Mode &mode, const PinConfig &pinConfig)
|
||||
{
|
||||
int pins[16];
|
||||
pinConfig.fill14Bit(pins);
|
||||
return VGA::init(mode, pins, 16, pinConfig.clock);
|
||||
}
|
||||
|
||||
bool init(const Mode &mode, const int *redPins, const int *greenPins, const int *bluePins, const int hsyncPin, const int vsyncPin, const int clockPin = -1)
|
||||
{
|
||||
int pinMap[16];
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
pinMap[i] = redPins[i];
|
||||
pinMap[i + 5] = greenPins[i];
|
||||
if (i < 4)
|
||||
pinMap[i + 10] = bluePins[i];
|
||||
}
|
||||
pinMap[14] = hsyncPin;
|
||||
pinMap[15] = vsyncPin;
|
||||
return VGA::init(mode, pinMap, 16, clockPin);
|
||||
}
|
||||
|
||||
virtual void initSyncBits()
|
||||
{
|
||||
hsyncBitI = mode.hSyncPolarity ? 0x4000 : 0;
|
||||
vsyncBitI = mode.vSyncPolarity ? 0x8000 : 0;
|
||||
hsyncBit = hsyncBitI ^ 0x4000;
|
||||
vsyncBit = vsyncBitI ^ 0x8000;
|
||||
}
|
||||
|
||||
virtual long syncBits(bool hSync, bool vSync)
|
||||
{
|
||||
return ((hSync ? hsyncBit : hsyncBitI) | (vSync ? vsyncBit : vsyncBitI)) * 0x10001;
|
||||
}
|
||||
|
||||
virtual int bytesPerSample() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
virtual float pixelAspect() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void propagateResolution(const int xres, const int yres)
|
||||
{
|
||||
setResolution(xres, yres);
|
||||
}
|
||||
|
||||
virtual void show(bool vSync = false)
|
||||
{
|
||||
if (!frameBufferCount)
|
||||
return;
|
||||
if (vSync)
|
||||
{
|
||||
vSyncPassed = false;
|
||||
while (!vSyncPassed)
|
||||
delay(0);
|
||||
}
|
||||
Graphics::show(vSync);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool useInterrupt()
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
void interruptPixelLine(int y, unsigned long *pixels, unsigned long syncBits)
|
||||
{
|
||||
unsigned short *line = frontBuffer[y];
|
||||
for (int i = 0; i < mode.hRes / 2; i++)
|
||||
{
|
||||
//writing two pixels improves speed drastically (avoids memory reads)
|
||||
pixels[i] = syncBits | (line[i * 2 + 1] & 0x3fff) | ((line[i * 2] & 0x3fff) << 16);
|
||||
}
|
||||
}
|
||||
};
|
114
libraries/bitluni_ESP32Lib/src/VGA/VGA3Bit.h
Normal file
114
libraries/bitluni_ESP32Lib/src/VGA/VGA3Bit.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
Author: bitluni 2019
|
||||
License:
|
||||
Creative Commons Attribution ShareAlike 4.0
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
For further details check out:
|
||||
https://youtube.com/bitlunislab
|
||||
https://github.com/bitluni
|
||||
http://bitluni.net
|
||||
*/
|
||||
#pragma once
|
||||
#include "VGA.h"
|
||||
#include "../Graphics/GraphicsR1G1B1A1X2S2Swapped.h"
|
||||
|
||||
class VGA3Bit : public VGA, public GraphicsR1G1B1A1X2S2Swapped
|
||||
{
|
||||
public:
|
||||
VGA3Bit() //8 bit based modes only work with I2S1
|
||||
: VGA(1)
|
||||
{
|
||||
}
|
||||
|
||||
bool init(const Mode &mode, const int RPin, const int GPin, const int BPin, const int hsyncPin, const int vsyncPin, const int clockPin = -1)
|
||||
{
|
||||
int pinMap[8] = {
|
||||
RPin,
|
||||
GPin,
|
||||
BPin,
|
||||
-1, -1, -1,
|
||||
hsyncPin, vsyncPin
|
||||
};
|
||||
|
||||
return VGA::init(mode, pinMap, 8, clockPin);
|
||||
}
|
||||
|
||||
bool init(const Mode &mode, const PinConfig &pinConfig)
|
||||
{
|
||||
int pins[8];
|
||||
pinConfig.fill3Bit(pins);
|
||||
return VGA::init(mode, pins, 8, pinConfig.clock);
|
||||
}
|
||||
|
||||
|
||||
virtual void initSyncBits()
|
||||
{
|
||||
hsyncBitI = mode.hSyncPolarity ? 0x40 : 0;
|
||||
vsyncBitI = mode.vSyncPolarity ? 0x80 : 0;
|
||||
hsyncBit = hsyncBitI ^ 0x40;
|
||||
vsyncBit = vsyncBitI ^ 0x80;
|
||||
SBits = hsyncBitI | vsyncBitI;
|
||||
}
|
||||
|
||||
virtual long syncBits(bool hSync, bool vSync)
|
||||
{
|
||||
return ((hSync ? hsyncBit : hsyncBitI) | (vSync ? vsyncBit : vsyncBitI)) * 0x1010101;
|
||||
}
|
||||
|
||||
virtual int bytesPerSample() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual float pixelAspect() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void propagateResolution(const int xres, const int yres)
|
||||
{
|
||||
setResolution(xres, yres);
|
||||
}
|
||||
|
||||
void *vSyncInactiveBuffer;
|
||||
void *vSyncActiveBuffer;
|
||||
void *inactiveBuffer;
|
||||
void *blankActiveBuffer;
|
||||
|
||||
virtual Color **allocateFrameBuffer()
|
||||
{
|
||||
return (Color **)DMABufferDescriptor::allocateDMABufferArray(yres, mode.hRes * bytesPerSample(), true, syncBits(false, false));
|
||||
}
|
||||
|
||||
virtual void allocateLineBuffers()
|
||||
{
|
||||
VGA::allocateLineBuffers((void **)frameBuffers[0]);
|
||||
}
|
||||
|
||||
virtual void show(bool vSync = false)
|
||||
{
|
||||
if (!frameBufferCount)
|
||||
return;
|
||||
if (vSync)
|
||||
{
|
||||
//TODO read the I2S docs to find out
|
||||
}
|
||||
Graphics::show(vSync);
|
||||
if(dmaBufferDescriptors)
|
||||
for (int i = 0; i < yres * mode.vDiv; i++)
|
||||
dmaBufferDescriptors[(mode.vFront + mode.vSync + mode.vBack + i) * 2 + 1].setBuffer(frontBuffer[i / mode.vDiv], mode.hRes * bytesPerSample());
|
||||
}
|
||||
|
||||
virtual void scroll(int dy, Color color)
|
||||
{
|
||||
Graphics::scroll(dy, color);
|
||||
if (frameBufferCount == 1)
|
||||
show();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void interrupt()
|
||||
{
|
||||
}
|
||||
};
|
139
libraries/bitluni_ESP32Lib/src/VGA/VGA3BitI.h
Normal file
139
libraries/bitluni_ESP32Lib/src/VGA/VGA3BitI.h
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
Author: bitluni 2019
|
||||
License:
|
||||
Creative Commons Attribution ShareAlike 4.0
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
For further details check out:
|
||||
https://youtube.com/bitlunislab
|
||||
https://github.com/bitluni
|
||||
http://bitluni.net
|
||||
*/
|
||||
#pragma once
|
||||
#include "VGA.h"
|
||||
#include "../Graphics/GraphicsR1G1B1A1.h"
|
||||
|
||||
class VGA3BitI : public VGA, public GraphicsR1G1B1A1
|
||||
{
|
||||
public:
|
||||
VGA3BitI() //8 bit based modes only work with I2S1
|
||||
: VGA(1)
|
||||
{
|
||||
}
|
||||
|
||||
bool init(const Mode &mode, const int RPin, const int GPin, const int BPin, const int hsyncPin, const int vsyncPin, const int clockPin = -1)
|
||||
{
|
||||
int pinMap[8] = {
|
||||
RPin,
|
||||
GPin,
|
||||
BPin,
|
||||
-1, -1, -1,
|
||||
hsyncPin, vsyncPin
|
||||
};
|
||||
return VGA::init(mode, pinMap, 8, clockPin);
|
||||
}
|
||||
|
||||
bool init(const Mode &mode, const PinConfig &pinConfig)
|
||||
{
|
||||
int pins[8];
|
||||
pinConfig.fill3Bit(pins);
|
||||
return VGA::init(mode, pins, 8, pinConfig.clock);
|
||||
}
|
||||
|
||||
virtual void initSyncBits()
|
||||
{
|
||||
hsyncBitI = mode.hSyncPolarity ? 0x40 : 0;
|
||||
vsyncBitI = mode.vSyncPolarity ? 0x80 : 0;
|
||||
hsyncBit = hsyncBitI ^ 0x40;
|
||||
vsyncBit = vsyncBitI ^ 0x80;
|
||||
}
|
||||
|
||||
virtual long syncBits(bool hSync, bool vSync)
|
||||
{
|
||||
return ((hSync ? hsyncBit : hsyncBitI) | (vSync ? vsyncBit : vsyncBitI)) * 0x1010101;
|
||||
}
|
||||
|
||||
virtual int bytesPerSample() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual float pixelAspect() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void propagateResolution(const int xres, const int yres)
|
||||
{
|
||||
setResolution(xres, yres);
|
||||
}
|
||||
|
||||
virtual void show(bool vSync = false)
|
||||
{
|
||||
if (!frameBufferCount)
|
||||
return;
|
||||
if (vSync)
|
||||
{
|
||||
vSyncPassed = false;
|
||||
while (!vSyncPassed)
|
||||
delay(0);
|
||||
}
|
||||
Graphics::show(vSync);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool useInterrupt()
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
void interrupt()
|
||||
{
|
||||
unsigned long *signal = (unsigned long *)dmaBufferDescriptors[dmaBufferDescriptorActive].buffer();
|
||||
unsigned long *pixels = &((unsigned long *)dmaBufferDescriptors[dmaBufferDescriptorActive].buffer())[(mode.hSync + mode.hBack) / 4];
|
||||
unsigned long base, baseh;
|
||||
if (currentLine >= mode.vFront && currentLine < mode.vFront + mode.vSync)
|
||||
{
|
||||
baseh = syncBits(true, true);
|
||||
base = syncBits(false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
baseh = syncBits(true, false);
|
||||
base = syncBits(false, false);
|
||||
}
|
||||
for (int i = 0; i < mode.hSync / 4; i++)
|
||||
signal[i] = baseh;
|
||||
for (int i = mode.hSync / 4; i < (mode.hSync + mode.hBack) / 4; i++)
|
||||
signal[i] = base;
|
||||
|
||||
int y = (currentLine - mode.vFront - mode.vSync - mode.vBack) / mode.vDiv;
|
||||
if (y >= 0 && y < mode.vRes)
|
||||
interruptPixelLine(y, pixels, base);
|
||||
else
|
||||
for (int i = 0; i < mode.hRes / 4; i++)
|
||||
{
|
||||
pixels[i] = base;
|
||||
}
|
||||
for (int i = 0; i < mode.hFront / 4; i++)
|
||||
signal[i + (mode.hSync + mode.hBack + mode.hRes) / 4] = base;
|
||||
currentLine = (currentLine + 1) % totalLines;
|
||||
dmaBufferDescriptorActive = (dmaBufferDescriptorActive + 1) % dmaBufferDescriptorCount;
|
||||
if (currentLine == 0)
|
||||
vSync();
|
||||
}
|
||||
|
||||
void interruptPixelLine(int y, unsigned long *pixels, unsigned long syncBits)
|
||||
{
|
||||
unsigned char *line = frontBuffer[y];
|
||||
int j = 0;
|
||||
for (int i = 0; i < mode.hRes / 4; i++)
|
||||
{
|
||||
int p0 = (line[j] >> 0) & 7;
|
||||
int p1 = (line[j++] >> 4) & 7;
|
||||
int p2 = (line[j] >> 0) & 7;
|
||||
int p3 = (line[j++] >> 4) & 7;
|
||||
pixels[i] = syncBits | (p2 << 0) | (p3 << 8) | (p0 << 16) | (p1 << 24);
|
||||
}
|
||||
}
|
||||
};
|
131
libraries/bitluni_ESP32Lib/src/VGA/VGA6Bit.h
Normal file
131
libraries/bitluni_ESP32Lib/src/VGA/VGA6Bit.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
Author: bitluni 2019
|
||||
License:
|
||||
Creative Commons Attribution ShareAlike 4.0
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
For further details check out:
|
||||
https://youtube.com/bitlunislab
|
||||
https://github.com/bitluni
|
||||
http://bitluni.net
|
||||
*/
|
||||
#pragma once
|
||||
#include "VGA.h"
|
||||
#include "../Graphics/GraphicsR2G2B2S2Swapped.h"
|
||||
|
||||
class VGA6Bit : public VGA, public GraphicsR2G2B2S2Swapped
|
||||
{
|
||||
public:
|
||||
VGA6Bit() //8 bit based modes only work with I2S1
|
||||
: VGA(1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool init(Mode &mode,
|
||||
const int R0Pin, const int R1Pin,
|
||||
const int G0Pin, const int G1Pin,
|
||||
const int B0Pin, const int B1Pin,
|
||||
const int hsyncPin, const int vsyncPin, const int clockPin = -1)
|
||||
{
|
||||
int pinMap[8] = {
|
||||
R0Pin, R1Pin,
|
||||
G0Pin, G1Pin,
|
||||
B0Pin, B1Pin,
|
||||
hsyncPin, vsyncPin
|
||||
};
|
||||
|
||||
return VGA::init(mode, pinMap, 8, clockPin);
|
||||
}
|
||||
|
||||
bool init(const Mode &mode, const int *redPins, const int *greenPins, const int *bluePins, const int hsyncPin, const int vsyncPin, const int clockPin = -1)
|
||||
{
|
||||
int pinMap[8];
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
pinMap[i] = redPins[i];
|
||||
pinMap[i + 2] = greenPins[i];
|
||||
pinMap[i + 4] = bluePins[i];
|
||||
}
|
||||
pinMap[6] = hsyncPin;
|
||||
pinMap[7] = vsyncPin;
|
||||
return VGA::init(mode, pinMap, 8, clockPin);
|
||||
}
|
||||
|
||||
bool init(const Mode &mode, const PinConfig &pinConfig)
|
||||
{
|
||||
int pins[8];
|
||||
pinConfig.fill6Bit(pins);
|
||||
return VGA::init(mode, pins, 8, pinConfig.clock);
|
||||
}
|
||||
|
||||
virtual void initSyncBits()
|
||||
{
|
||||
hsyncBitI = mode.hSyncPolarity ? 0x40 : 0;
|
||||
vsyncBitI = mode.vSyncPolarity ? 0x80 : 0;
|
||||
hsyncBit = hsyncBitI ^ 0x40;
|
||||
vsyncBit = vsyncBitI ^ 0x80;
|
||||
SBits = hsyncBitI | vsyncBitI;
|
||||
}
|
||||
|
||||
virtual long syncBits(bool hSync, bool vSync)
|
||||
{
|
||||
return ((hSync ? hsyncBit : hsyncBitI) | (vSync ? vsyncBit : vsyncBitI)) * 0x1010101;
|
||||
}
|
||||
|
||||
virtual int bytesPerSample() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual float pixelAspect() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void propagateResolution(const int xres, const int yres)
|
||||
{
|
||||
setResolution(xres, yres);
|
||||
}
|
||||
|
||||
void *vSyncInactiveBuffer;
|
||||
void *vSyncActiveBuffer;
|
||||
void *inactiveBuffer;
|
||||
void *blankActiveBuffer;
|
||||
|
||||
virtual Color **allocateFrameBuffer()
|
||||
{
|
||||
return (Color **)DMABufferDescriptor::allocateDMABufferArray(yres, mode.hRes * bytesPerSample(), true, syncBits(false, false));
|
||||
}
|
||||
|
||||
virtual void allocateLineBuffers()
|
||||
{
|
||||
VGA::allocateLineBuffers((void **)frameBuffers[0]);
|
||||
}
|
||||
|
||||
virtual void show(bool vSync = false)
|
||||
{
|
||||
if (!frameBufferCount)
|
||||
return;
|
||||
if (vSync)
|
||||
{
|
||||
//TODO read the I2S docs to find out
|
||||
}
|
||||
Graphics::show(vSync);
|
||||
if(dmaBufferDescriptors)
|
||||
for (int i = 0; i < yres * mode.vDiv; i++)
|
||||
dmaBufferDescriptors[(mode.vFront + mode.vSync + mode.vBack + i) * 2 + 1].setBuffer(frontBuffer[i / mode.vDiv], mode.hRes * bytesPerSample());
|
||||
}
|
||||
|
||||
virtual void scroll(int dy, Color color)
|
||||
{
|
||||
Graphics::scroll(dy, color);
|
||||
if (frameBufferCount == 1)
|
||||
show();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void interrupt()
|
||||
{
|
||||
}
|
||||
};
|
157
libraries/bitluni_ESP32Lib/src/VGA/VGA6BitI.h
Normal file
157
libraries/bitluni_ESP32Lib/src/VGA/VGA6BitI.h
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
Author: bitluni 2019
|
||||
License:
|
||||
Creative Commons Attribution ShareAlike 4.0
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
|
||||
For further details check out:
|
||||
https://youtube.com/bitlunislab
|
||||
https://github.com/bitluni
|
||||
http://bitluni.net
|
||||
*/
|
||||
#pragma once
|
||||
#include "VGA.h"
|
||||
#include "../Graphics/GraphicsR2G2B2A2.h"
|
||||
|
||||
class VGA6BitI : public VGA, public GraphicsR2G2B2A2
|
||||
{
|
||||
public:
|
||||
VGA6BitI() //8 bit based modes only work with I2S1
|
||||
: VGA(1)
|
||||
{
|
||||
}
|
||||
|
||||
bool init(Mode &mode,
|
||||
const int R0Pin, const int R1Pin,
|
||||
const int G0Pin, const int G1Pin,
|
||||
const int B0Pin, const int B1Pin,
|
||||
const int hsyncPin, const int vsyncPin, const int clockPin = -1)
|
||||
{
|
||||
int pinMap[8] = {
|
||||
R0Pin, R1Pin,
|
||||
G0Pin, G1Pin,
|
||||
B0Pin, B1Pin,
|
||||
hsyncPin, vsyncPin
|
||||
};
|
||||
|
||||
return VGA::init(mode, pinMap, 8, clockPin);
|
||||
}
|
||||
|
||||
bool init(const Mode &mode, const int *redPins, const int *greenPins, const int *bluePins, const int hsyncPin, const int vsyncPin, const int clockPin = -1)
|
||||
{
|
||||
int pinMap[8];
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
pinMap[i] = redPins[i];
|
||||
pinMap[i + 2] = greenPins[i];
|
||||
pinMap[i + 4] = bluePins[i];
|
||||
}
|
||||
pinMap[6] = hsyncPin;
|
||||
pinMap[7] = vsyncPin;
|
||||
return VGA::init(mode, pinMap, 8, clockPin);
|
||||
}
|
||||
|
||||
bool init(const Mode &mode, const PinConfig &pinConfig)
|
||||
{
|
||||
int pins[8];
|
||||
pinConfig.fill6Bit(pins);
|
||||
return VGA::init(mode, pins, 8, pinConfig.clock);
|
||||
}
|
||||
|
||||
virtual void initSyncBits()
|
||||
{
|
||||
hsyncBitI = mode.hSyncPolarity ? 0x40 : 0;
|
||||
vsyncBitI = mode.vSyncPolarity ? 0x80 : 0;
|
||||
hsyncBit = hsyncBitI ^ 0x40;
|
||||
vsyncBit = vsyncBitI ^ 0x80;
|
||||
}
|
||||
|
||||
virtual long syncBits(bool hSync, bool vSync)
|
||||
{
|
||||
return ((hSync ? hsyncBit : hsyncBitI) | (vSync ? vsyncBit : vsyncBitI)) * 0x1010101;
|
||||
}
|
||||
|
||||
virtual int bytesPerSample() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual float pixelAspect() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void propagateResolution(const int xres, const int yres)
|
||||
{
|
||||
setResolution(xres, yres);
|
||||
}
|
||||
|
||||
virtual void show(bool vSync = false)
|
||||
{
|
||||
if (!frameBufferCount)
|
||||
return;
|
||||
if (vSync)
|
||||
{
|
||||
vSyncPassed = false;
|
||||
while (!vSyncPassed)
|
||||
delay(0);
|
||||
}
|
||||
Graphics::show(vSync);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool useInterrupt()
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
void interrupt()
|
||||
{
|
||||
unsigned long *signal = (unsigned long *)dmaBufferDescriptors[dmaBufferDescriptorActive].buffer();
|
||||
unsigned long *pixels = &((unsigned long *)dmaBufferDescriptors[dmaBufferDescriptorActive].buffer())[(mode.hSync + mode.hBack) / 4];
|
||||
unsigned long base, baseh;
|
||||
if (currentLine >= mode.vFront && currentLine < mode.vFront + mode.vSync)
|
||||
{
|
||||
baseh = syncBits(true, true);
|
||||
base = syncBits(false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
baseh = syncBits(true, false);
|
||||
base = syncBits(false, false);
|
||||
}
|
||||
for (int i = 0; i < mode.hSync / 4; i++)
|
||||
signal[i] = baseh;
|
||||
for (int i = mode.hSync / 4; i < (mode.hSync + mode.hBack) / 4; i++)
|
||||
signal[i] = base;
|
||||
|
||||
int y = (currentLine - mode.vFront - mode.vSync - mode.vBack) / mode.vDiv;
|
||||
if (y >= 0 && y < mode.vRes)
|
||||
interruptPixelLine(y, pixels, base);
|
||||
else
|
||||
for (int i = 0; i < mode.hRes / 4; i++)
|
||||
{
|
||||
pixels[i] = base;
|
||||
}
|
||||
for (int i = 0; i < mode.hFront / 4; i++)
|
||||
signal[i + (mode.hSync + mode.hBack + mode.hRes) / 4] = base;
|
||||
currentLine = (currentLine + 1) % totalLines;
|
||||
dmaBufferDescriptorActive = (dmaBufferDescriptorActive + 1) % dmaBufferDescriptorCount;
|
||||
if (currentLine == 0)
|
||||
vSync();
|
||||
}
|
||||
|
||||
void interruptPixelLine(int y, unsigned long *pixels, unsigned long syncBits)
|
||||
{
|
||||
unsigned char *line = frontBuffer[y];
|
||||
int j = 0;
|
||||
for (int i = 0; i < mode.hRes / 4; i++)
|
||||
{
|
||||
int p0 = (line[j] >> 0) & 7;
|
||||
int p1 = (line[j++] >> 4) & 7;
|
||||
int p2 = (line[j] >> 0) & 7;
|
||||
int p3 = (line[j++] >> 4) & 7;
|
||||
pixels[i] = syncBits | (p2 << 0) | (p3 << 8) | (p0 << 16) | (p1 << 24);
|
||||
}
|
||||
}
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue