//
/*
* this code is a basic 'get you up and running' code
* and is rough and ready. It is availble to help you
* figure things out. Hopefully you can improve on it.
* mortonkopf
*/
//based on timings from Lukas Hartmann
//also added the drawing functions from Lukas.
//https://www.youtube.com/watch?v=FfxH6zlsDGo
// using 72MHz Teensy 3.1
// using resistors on outputs to derive c0.7v signals
//based on wiring from Nick Gammon VGA page
#define Width 200 //sreen pixels
#define Height 200 //screen pixels
/////for spiral pattern///////
unsigned long runTime = 0;
float sx = 0, sy = 0;
uint16_t xx = 0, xx1 = 0, yy = 0, yy1 = 0;
/////////////
#include <SdFat.h>
SdFat sd;
SdFile myFile;
const int chipSelect = 10;
unsigned long bitmapOffset = 54;//0x36;
uint8_t lcdBuffer[Height*Width];
// PortB[0:3, 16:19] = {16, 17, 19, 18, 0, 1, 32, 25}
/* Teensy external pin number / GPIO port / bit of port
0 B 16
1 B 17
16 B 0
17 B 1
18 B 3
19 B 2
25 B 19
32 B 18
*/
//* bit colour values from bitmap will be?
//Bit 7 6 5 4 3 2 1 0
//Data R R R G G G B B
// VGA PINS
#define RGB_OUT GPIOB_PDOR
#define PIN_VR1 18//16
#define PIN_VR2 19//17
#define PIN_VG1 16//19
#define PIN_VG2 17//18
#define PIN_VB1 0
#define PIN_VB2 1
#define PIN_VBLANK 8
#define PIN_HBLANK 7
//#define RED B00110000
//#define BLUE B00000011
//#define GREEN B00001100
//byte colours[6] = {0x01,0x02,0x04,0x08,0x10,0x20};//option for calling all single bit/pin values r,r,b,b,g,g
static volatile int VSYNC = 0;
#define NOP asm volatile("nop\n\t");
volatile uint32_t currentLine = 0;
volatile uint32_t currentFrame = 0;
IntervalTimer timer0;
#define UPPER_BORDER 40
void timerLine() {
cli();
if (currentLine>1) {
digitalWrite(PIN_VBLANK, 1);
} else {
digitalWrite(PIN_VBLANK, 0);
}
digitalWrite(PIN_HBLANK, 0);
RGB_OUT = 0x00;
RGB_OUT = 0x00;
RGB_OUT = 0x00;
RGB_OUT = 0x00;
digitalWrite(PIN_HBLANK, 1);
currentLine++;
currentLine = currentLine%525;
NOP;
uint32_t y = (currentLine - UPPER_BORDER)>>1;//>>2;//how many rows to duplicate (to square up the image)
//display output section is within the timer >>
if (y>=0 && y<Height){ //for each row do
for (int i=0; i<40; i++) {//left edge buffer
RGB_OUT = 0;
}
uint8_t* displayPointer = lcdBuffer + Width*y;
for (int x=0; x<Width; x++) {
uint32_t color = *(displayPointer++);
color = color | (color<<12); //shift bits
RGB_OUT = color;
// RGB_OUT = color;
// RGB_OUT = color;
// RGB_OUT = color; //four calls wide to square up each pixel
}//end of one row of pixels
}//end of display output section
VSYNC = 0;
if (y==Height) {
VSYNC = 1;
}
RGB_OUT = 0;
sei();
}
void setup() {
delay(500);
// Initialize SdFat or print a detailed error message and halt
if (!sd.begin(chipSelect, SPI_FULL_SPEED)) sd.initErrorHalt();
//////-------------------------////////////
delay(500);
pinMode(PIN_VR1, OUTPUT);
pinMode(PIN_VG1, OUTPUT);
pinMode(PIN_VB1, OUTPUT);
pinMode(PIN_VR2, OUTPUT);
pinMode(PIN_VG2, OUTPUT);
pinMode(PIN_VB2, OUTPUT);
pinMode(PIN_VBLANK, OUTPUT);
pinMode(PIN_HBLANK, OUTPUT);
pinMode(23, INPUT);//for input for patterns controlled by abalogue input?
timer0.begin(timerLine, 31.468);
}
unsigned int tick = 0;
int t=0;
int y =0;
void loop()
{
if (VSYNC==1) {
tick++;
VSYNC=0;
//---------------in this section we can fill the buffer with our colours------//
//display a bmp from sd card
//displayBMP("holly21.bmp"); //bmp needs to be 8bit bmp
spiral();
//drawCircle(100,100,50,0x1); // DRAW the circle
maths1();
//fill the screen with a colour
//fillScreen(0x0);
//then draw a diagonal series of dots
// drawLine(10,10,100,100,0x1);
//then draw a line
// for(int x=0;x<100;x++){
// putPixel(x,10,0x1);
// }
}
}
//------------drawing functions-------------------------//
void drawPixel(int x0,int y0,uint8_t color) {
lcdBuffer[y0*Width+x0] = color;
}
void drawLine(int x0, int y0, int x1, int y1, uint8_t color) {
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
int err = (dx>dy ? dx : -dy)/2, e2;
for(;;){
drawPixel(x0,y0,color);
if (x0==x1 && y0==y1) break;
e2 = err;
if (e2 >-dx) { err -= dy; x0 += sx; }
if (e2 < dy) { err += dx; y0 += sy; }
}
}
void fillScreen(uint8_t c) {
for (int y=0; y<Height; y++) {
for (int x=0; x<Width; x++) {
lcdBuffer[y*Width+x] = c;
}
}
}
//----------------------------//
void drawCircle(int xm, int ym, int r, int col){ //centre values
int x = -r, y = 0, err = 2-2*r; /* bottom left to top right */
do {
drawPixel(xm-x, ym+y,col); /* I. Quadrant +x +y */
drawPixel(xm-y, ym-x,col); /* II. Quadrant -x +y */
drawPixel(xm+x, ym-y,col); /* III. Quadrant -x -y */
drawPixel(xm+y, ym+x,col); /* IV. Quadrant +x -y */
r = err;
if (r <= y) err += ++y*2+1; /* e_xy+e_y < 0 */
if (r > x || err > y) /* e_xy+e_x > 0 or no 2nd y-step */
err += ++x*2+1; /* -> x-step now */
} while (x < 0);
}
//------------use a bmp to load values into buffer---------------//
void displayBMP(char* filename){ //this is really flakey on the numbers for pad1 to make it work
//----------------------------------------------------//
//open the file for reading:
if (!myFile.open(filename/*"holly.bmp"*/, O_READ)) {
sd.errorHalt("opening file for read failed");
}
int pad1 = Width*6; //for the colour table ref for 8bit bmp? //these pad values are trial and error for me
byte data;
byte dataG, dataB, dataR, pix;
int row,col;
// loop through each pixel in the file
for(int j=pad1; j<(Height*Width)+(pad1-Width);j++){
//set position in file to read
int x = bitmapOffset+j;
myFile.seekSet(x);
data = myFile.read();
//attempt to move 8bit colour to 6pins of output using bit mask- might not be right
dataR = data & B00000011; //should this be &= ?
dataB = data & B00011000;
dataG = data & B11000000;
pix = (dataG>>2) + (dataB) + dataR;
//put the data into the buffer - but is upside down?
lcdBuffer[j-pad1+109] = pix;
}
// close the file:
myFile.close();
}
//---------------end of displaybmp------------------------------------//
//---------------patternFrac-------------------------//
/* https://github.com/pixelmatix/aurora
* based on Copyright (c) 2014 Jason Coon
*/
int time = 0;
int cycles = 0;
int16_t v;
int z;
void patternFrac() {
for (int x = 0; x < Width; x++) {
for (int y = 0; y < Height; y++) {
v = 0;
uint8_t wibble = (time);
v += (x * wibble * 2 + time);
v += (y * (128 - wibble) * 2 + time);
v += (y * x * (-time) / 2);
// if(((v>>8)+127)>20) {
lcdBuffer[y*Width+x] = (v >> 8) + 127;
// }
// else { lcdBuffer[y*Width+x] = 0;}
}
}
time += 1;
cycles++;
if (cycles >= 750) {
time = 0;
cycles = 0;
}
}
//-------------------------------end of pattern--------------//
//--------------------------maths1 pattern------------------//
int deep =65;
void maths1(){
for(int number=0;number<150;number++){
for (int x = 0; x < Width; x++) {
for (int y = 0; y < Height; y++) {
v = 0;
uint8_t wibble = (time);
v += (x * wibble * 2 + time);
v += (y * (128 - wibble) * 2 + time);
v += (y * x * (-time) / 2);
if(((v>>8)+127)>deep) {
lcdBuffer[y*Width+x] = (v >> 8) + 127;}
else { lcdBuffer[y*Width+x] = 0;}
}
}
deep +=1;
time += 1;
cycles++;
if (cycles >= 180) { //keep cycles and deep max lengths different for more interesting pattern variation
deep =65;
time = 0;
cycles = 0;
}
}
//second part
deep = 245;
cycles = 170;
time=0;
for(int number=0;number<170;number++){
for (int x = 0; x < Width; x++) {
for (int y = 0; y < Height; y++) {
v = 0;
uint8_t wibble = (time);
v += (x * wibble * 2 + time);
v += (y * (128 - wibble) * 2 + time);
v += (y * x * (-time) / 2);
if(((v>>8)+127)>deep) {
lcdBuffer[y*Width+x] = (v >> 8) + 127;}
else { lcdBuffer[y*Width+x] = 0;}
}
}
deep -=1;
time -= 1;
cycles--;
}
}
//------------------------------------------------//
//--------spiral pattern----------------//
void spiral(){
fillScreen(0x0);
byte c = random(0x01,0x40);
int n = random(12, 30), r = random(25, 55);
// Rainbow patern generator
// Alan Senior 22/2/15
for (long i = 0; i < (360 * n); i++) {
sx = cos((i / n - 90) * 0.0174532925);
sy = sin((i / n - 90) * 0.0174532925);
xx = sx * (20 - r) + 100;
yy = sy * (20 - r) + 100;
sy = cos(((i % 360) - 90) * 0.0174532925);
sx = sin(((i % 360) - 90) * 0.0174532925);
xx1 = sx * r + xx;
yy1 = sy * r + yy;
drawPixel(xx1, yy1, c);
}
byte cc =random(0x01,0x40);
n = random(2, 20),
r = random(30, 55);
for (long i = 0; i < (360 * n); i++) {
sx = cos((i / n - 90) * 0.0174532925);
sy = sin((i / n - 90) * 0.0174532925);
xx = sx * (20 - r) + 100;
yy = sy * (20 - r) + 100;
sy = cos(((i % 360) - 90) * 0.0174532925);
sx = sin(((i % 360) - 90) * 0.0174532925);
xx1 = sx * r + xx;
yy1 = sy * r + yy;
drawPixel(xx1, yy1, cc);//i
}fillScreen(0x00);
}
//---------end of sprial pattern--------------------//