/* 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(); } } }