Add Library

This commit is contained in:
Siwat Sirichai 2019-08-09 09:01:56 +07:00
parent e365b9dbd9
commit 3c47103b39
318 changed files with 56465 additions and 0 deletions

View 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);
}
};

View 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;
}
};

View 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)
{
}

View 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);
};

View 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()
{
}
};

View 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);
}
}
};

View 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()
{
}
};

View 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);
}
}
};

View 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()
{
}
};

View 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);
}
}
};