/*
Firmware for a Macintosh display adapter connected over USB
Copyright (C) 2010 Jeroen Domburg
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "sysinit.h"
#include "lpc134x.h"
#include
#include "usb.h"
#include "gpio.h"
//Mac display = 512x342
//Pixel clock = 15.6672MHz
//Refresh freq = 60.15
//Scan rate: 22KHz (?)
//Vbl = 28 scan lines
//Hbl = 192 pixels
// Total: 714x370 'pixels'
//1 line = 64 bytes aan data
//Ok, the HBL is really funky and actually a HDrive...
//More info: http://members.optusnet.com.au/eviltim/macmp3/macmp3.htm
/*
Timings:
Per line: 512 pixels, 202 non-visible 'pixels'
SPI FIFO buffer is 128 pixels -> 384 pixels in which we have to keep pushing the buffer, 330 in which we don't.
*/
#define NOP() __asm volatile ("NOP")
#define LEDPORT 2
#define LEDBIT 6
#define HSYNCPORT 0
#define HSYNCBIT 10 //=CT16B0_MAT2
#define VSYNCPORT 0
#define VSYNCBIT 7
#define VIDEOPORT 0
#define VIDEOBIT 9
#define DRAMDPORT 1
#define DRAMAPORT 1
//DRAM D pins: P1_8 - P1_11
//DRAM A pins: P1_0 - P1-7
#define DRAMDMASK 0x0F00
#define DRAMDSHIFT 8
#define DRAMAMASK 0x00FF
#define DRAMASHIFT 0
#define DRAMWPORT 3
#define DRAMWBIT 1
#define DRAMRASPORT 3
#define DRAMRASBIT 0
#define DRAMCASPORT 3
#define DRAMCASBIT 3
#define DRAMGPORT 2
#define DRAMGBIT 11
#define GPIOFANPORT 2
#define GPIOFANBIT 4
#define GPIOMONPORT 2
#define GPIOMONBIT 2
#define GPIOEJECTPORT 2
#define GPIOEJECTBIT 10
#define GPIOHDLEDPORT 3
#define GPIOHDLEDBIT 2
#define SENDLINE_BUFFER 1
#define SENDLINE_FREETIME 2
volatile int linePos;
volatile int wordPos;
volatile int dramRow=0;
volatile int doSendLine;
char usbData[64];
int usbDataLen;
int usbDataProcessed;
struct GpioPins_t {
int port;
int bit;
};
const struct GpioPins_t gpioPins[]={
{GPIOFANPORT, GPIOFANBIT}, //Fan enable
{GPIOMONPORT, GPIOMONBIT}, //Monitor enable
{GPIOEJECTPORT, GPIOEJECTBIT}, //Floppy eject
{GPIOHDLEDPORT, GPIOHDLEDBIT}, //HD led
};
void gpioSet(int gpio, int val) {
if (gpio>=4) return;
if (val) {
GPIOSET(gpioPins[gpio].port, gpioPins[gpio].bit);
} else {
GPIOCLEAR(gpioPins[gpio].port, gpioPins[gpio].bit);
}
}
//Timing note: One NOP is 13ns.
//Takes a while to set up the line, so this should be called a bit before the real data has to be sent.
void sendLine(int line) {
int dramCol;
GPIOCLEAR(LEDPORT, LEDBIT);
GPIOMOD(DRAMAPORT, DRAMAMASK, line<>DRAMDSHIFT); \
GPIOSET(DRAMCASPORT, DRAMCASBIT);
int from=0; int to=128;
if (line>=256) {
from=128;
to=256;
}
for (dramCol=from; dramCol32) state=stSync;
//Pre-calc row and col.
row=(pos>>6);
if (pos<16384) {
col=(pos&0x3f)<<1;
} else {
col=((pos&0x3f)|0x40)<<1;
}
state=stRunningFirst;
break;
case stRunning:
case stRunningFirst:
if (state==stRunningFirst || (firstlast&1)) {
GPIO_GPIO1DIR=DRAMDMASK|DRAMAMASK;
GPIOMOD(DRAMAPORT, DRAMAMASK, row<>4)<=256?128:0))<>4)&0xf;
GPIOMOD(DRAMDPORT, DRAMDMASK, i<=256?128:0))<=VIDEOLINESTART && linePos>=4;
i=inv[i&0xf];
*/
if ((dramRow)&1) i=0xa; else i=0x5;
GPIOMOD(DRAMDPORT, DRAMDMASK, i<0) {
int x;
int firstlast;
int credits;
#define STARTCREDS 1
firstlast=1;
credits=STARTCREDS;
while (firstlast!=2) {
if (credits<0) firstlast|=2;
if ((usbDataProcessed+1)==usbDataLen) firstlast|=2;
credits-=processByte(usbData[usbDataProcessed++], firstlast);
if (usbDataProcessed==usbDataLen) {
firstlast=2;
usbDataLen=0;
usbDataProcessed=0;
}
firstlast&=(~1);
}
} else {
usbHandle();
}
}
}