From c9fe8edc29446d33816a45868b9e6e1fdfdffb63 Mon Sep 17 00:00:00 2001 From: Jorj Bauer Date: Mon, 6 Jul 2020 07:04:22 -0400 Subject: [PATCH] first pass at Teensy 4.1 support --- apple/nibutil.h | 2 + teensy/parallelsram.cpp | 218 ---------------- teensy/parallelsram.h | 25 -- teensy/teensy-display.cpp | 467 ++++++---------------------------- teensy/teensy-display.h | 36 +-- teensy/teensy-filemanager.cpp | 24 +- teensy/teensy-filemanager.h | 10 +- teensy/teensy-speaker.cpp | 3 +- teensy/teensy.ino | 19 +- 9 files changed, 106 insertions(+), 698 deletions(-) delete mode 100644 teensy/parallelsram.cpp delete mode 100644 teensy/parallelsram.h diff --git a/apple/nibutil.h b/apple/nibutil.h index 3ea916d..81e947f 100644 --- a/apple/nibutil.h +++ b/apple/nibutil.h @@ -2,7 +2,9 @@ #define __NIBUTIL_H #include +#ifndef TEENSYDUINO #include +#endif #include #include #include diff --git a/teensy/parallelsram.cpp b/teensy/parallelsram.cpp deleted file mode 100644 index 032108a..0000000 --- a/teensy/parallelsram.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "parallelsram.h" - -// Assumes any Output Enable pin is hardwired-enabled; -// any Chip Enable pin is hardwared-enabled. -// -// Uses the low 8 bits of Port D as I/O lines (2, 14, 7, 8, 6, 20, 21, 5). -// -// R/W (aka WriteEnable) is on pin 31. - -#define RAM_RW 34 - -// The Address pins (19 of them). It would be nice to have these -// easily bitwise-manipulable, instead of having to set each bit -// individually. -// -// We can use 12 bits of Port C: 15, 22, 23, 9, 10, 13, 11, 12, 35, 36, 37, 38 -// And then 6 bits of Port B: 16 17 19 18 49 50 -// -// And hard wire one bit low (we don't need all 19 lines). That gets us -// 256 Kb of RAM which should be sufficient. - -static uint8_t addrPins[] = { 15, 22, 23, 9, 10, 13, 11, 12, 35, 36, 37, 38, - 16, 17, 19, 18, 49, 50 -}; - -#if 0 -#define DELAY { delayMicroseconds(1); /* overkill, but useful for debugging */ } -#else -#define DELAY { __asm__ volatile ("nop"); __asm__ volatile ("nop"); \ -__asm__ volatile ("nop"); __asm__ volatile ("nop"); \ -__asm__ volatile ("nop"); __asm__ volatile ("nop"); \ -__asm__ volatile ("nop"); __asm__ volatile ("nop"); \ - } -#endif - -#define OE_ON { /*if (noe != 255) {digitalWrite(noe, LOW);}*/ } -#define OE_OFF { /*if (noe != 255) {digitalWrite(noe, HIGH);}*/ } - -#define CE_ON { /*if (n_ce != 255) {digitalWrite(n_ce, LOW);} if (p_ce != 255) { digitalWrite(p_ce, HIGH); }*/ } -#define CE_OFF { /*if (n_ce != 255) {digitalWrite(n_ce, HIGH);} if (p_ce != 255) { digitalWrite(p_ce, LOW); }*/ } - -#define WE_ON { digitalWriteFast(RAM_RW, LOW); } -#define WE_OFF { digitalWriteFast(RAM_RW, HIGH); } - -ParallelSRAM::ParallelSRAM() -{ - pinMode(RAM_RW, OUTPUT); - - // Port D is our I/O port. Use the AVR emulation layer to set up the - // pins once, and then we'll just fiddle with the DDR, input, and - // output directly. - - // Enable it as a digital port... - // SIM_SCGC5 |= SIM_SCGC5_PORTD; - //... what else? How do we set PORTD_PCR[0-7]? - - pinMode(2, INPUT); - pinMode(14, INPUT); - pinMode(7, INPUT); - pinMode(8, INPUT); - pinMode(6, INPUT); - pinMode(20, INPUT); - pinMode(21, INPUT); - pinMode(5, INPUT); - isInput = true; - - // Set up the address pins - for (int i=0; i> 12); - -#if 0 - for (uint8_t i=0; i - -class ParallelSRAM { - public: - ParallelSRAM(); - ~ParallelSRAM(); - - void SetPins(); - - uint8_t read(uint32_t addr); - void write(uint32_t addr, uint8_t v); - - protected: - uint8_t getInput(); - void setOutput(uint8_t v); - void setAddress(uint32_t addr); - - private: - bool isInput; -}; - -#endif diff --git a/teensy/teensy-display.cpp b/teensy/teensy-display.cpp index 8d80fca..6ec96d9 100644 --- a/teensy/teensy-display.cpp +++ b/teensy/teensy-display.cpp @@ -4,208 +4,91 @@ #include "bios-font.h" #include "appleui.h" -#define RS 16 -#define WR 17 -#define CS 18 -#define RST 19 +#define _clock 65000000 -// Ports C&D of the Teensy connected to DB of the display -#define DB_0 15 -#define DB_1 22 -#define DB_2 23 -#define DB_3 9 -#define DB_4 10 -#define DB_5 13 -#define DB_6 11 -#define DB_7 12 -#define DB_8 2 -#define DB_9 14 -#define DB_10 7 -#define DB_11 8 -#define DB_12 6 -#define DB_13 20 -#define DB_14 21 -#define DB_15 5 +#define PIN_RST 8 +#define PIN_DC 9 +#define PIN_CS 10 +#define PIN_MOSI 11 +#define PIN_MISO 12 +#define PIN_SCK 13 #define disp_x_size 239 #define disp_y_size 319 -#define setPixel(color) { LCD_Write_DATA(((color)>>8),((color)&0xFF)); } // 565 RGB - #include "globals.h" #include "applevm.h" +ILI9341_t3 tft = ILI9341_t3(PIN_CS, PIN_DC, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO); + // RGB map of each of the lowres colors -const uint8_t loresPixelColors[16*2] = { 0x00,0x00, // 0 black - 0xC0,0x06, // 1 magenta - 0x00,0x10, // 2 dark blue - 0xA1,0xB5, // 3 purple - 0x04,0x80, // 4 dark green - 0x6B,0x4D, // 5 dark grey - 0x1B,0x9F, // 6 med blue - 0x0D,0xFD, // 7 light blue - 0x92,0xA5, // 8 brown - 0xF8,0xC5, // 9 orange - 0x95,0x55, // 10 light gray - 0xFC,0xF2, // 11 pink - 0x07,0xE0, // 12 green - 0xFF,0xE0, // 13 yellow - 0x87,0xF0, // 14 aqua - 0xFF,0xFF // 15 white +const uint16_t loresPixelColors[16] = { 0x0000, // 0 black + 0xC006, // 1 magenta + 0x0010, // 2 dark blue + 0xA1B5, // 3 purple + 0x0480, // 4 dark green + 0x6B4D, // 5 dark grey + 0x1B9F, // 6 med blue + 0x0DFD, // 7 light blue + 0x92A5, // 8 brown + 0xF8C5, // 9 orange + 0x9555, // 10 light gray + 0xFCF2, // 11 pink + 0x07E0, // 12 green + 0xFFE0, // 13 yellow + 0x87F0, // 14 aqua + 0xFFFF // 15 white }; -const uint8_t loresPixelColorsGreen[16*2] = { 0x00, 0x00, - 0x01, 0x40, - 0x00, 0x40, - 0x02, 0x80, - 0x03, 0x00, - 0x03, 0x40, - 0x03, 0x00, - 0x04, 0x80, - 0x02, 0xC0, - 0x02, 0x40, - 0x05, 0x00, - 0x05, 0x40, - 0x05, 0x80, - 0x07, 0x00, - 0x06, 0x80, - 0x07, 0xC0 +const uint16_t loresPixelColorsGreen[16] = { 0x0000, + 0x0140, + 0x0040, + 0x0280, + 0x0300, + 0x0340, + 0x0300, + 0x0480, + 0x02C0, + 0x0240, + 0x0500, + 0x0540, + 0x0580, + 0x0700, + 0x0680, + 0x07C0 }; -const uint8_t loresPixelColorsWhite[16*2] = { 0x00, 0x00, - 0x29, 0x45, - 0x08, 0x41, - 0x52, 0x8A, - 0x63, 0x0C, - 0x6B, 0x4D, - 0x63, 0x0C, - 0x94, 0x92, - 0x5A, 0xCB, - 0x4A, 0x49, - 0xA5, 0x14, - 0xAD, 0x55, - 0xB5, 0x96, - 0xE7, 0x1C, - 0xD6, 0x9A, - 0xFF, 0xDF +const uint16_t loresPixelColorsWhite[16] = { 0x0000, + 0x2945, + 0x0841, + 0x528A, + 0x630C, + 0x6B4D, + 0x630C, + 0x9492, + 0x5ACB, + 0x4A49, + 0xA514, + 0xAD55, + 0xB596, + 0xE71C, + 0xD69A, + 0xFFDF }; TeensyDisplay::TeensyDisplay() { memset(videoBuffer, 0, sizeof(videoBuffer)); - pinMode(DB_8, OUTPUT); - pinMode(DB_9, OUTPUT); - pinMode(DB_10, OUTPUT); - pinMode(DB_11, OUTPUT); - pinMode(DB_12, OUTPUT); - pinMode(DB_13, OUTPUT); - pinMode(DB_14, OUTPUT); - pinMode(DB_15, OUTPUT); - pinMode(DB_0, OUTPUT); - pinMode(DB_1, OUTPUT); - pinMode(DB_2, OUTPUT); - pinMode(DB_3, OUTPUT); - pinMode(DB_4, OUTPUT); - pinMode(DB_5, OUTPUT); - pinMode(DB_6, OUTPUT); - pinMode(DB_7, OUTPUT); - - P_RS = portOutputRegister(digitalPinToPort(RS)); - B_RS = digitalPinToBitMask(RS); - P_WR = portOutputRegister(digitalPinToPort(WR)); - B_WR = digitalPinToBitMask(WR); - P_CS = portOutputRegister(digitalPinToPort(CS)); - B_CS = digitalPinToBitMask(CS); - P_RST = portOutputRegister(digitalPinToPort(RST)); - B_RST = digitalPinToBitMask(RST); - - pinMode(RS,OUTPUT); - pinMode(WR,OUTPUT); - pinMode(CS,OUTPUT); - pinMode(RST,OUTPUT); - - // begin initialization - - sbi(P_RST, B_RST); - delay(5); - cbi(P_RST, B_RST); - delay(15); - sbi(P_RST, B_RST); - delay(15); - - cbi(P_CS, B_CS); - - // Setup here is from the document "Driver IC SSD1289.pdf" - // https://forum.allaboutcircuits.com/attachments/driver-ic-ssd1289-pdf.71570/ - LCD_Write_COM_DATA(0x00,0x0001); // R00h: enable the oscillator - LCD_Write_COM_DATA(0x03,0xA8A4); // power control [%1010 1000 1010 1000] == DCT3, DCT1, BT2, DC3, DC1, AP2 - - LCD_Write_COM_DATA(0x0C,0x0000); // power control2 [0] - LCD_Write_COM_DATA(0x0D,0x080C); // power control3 [VRH3, VRH2, invalid bits] - LCD_Write_COM_DATA(0x0E,0x2B00); // power control4 VCOMG, VDV3, VDV1, VDV0 - LCD_Write_COM_DATA(0x1E,0x00B7); // power control5 nOTP, VCM5, VCM4, VCM2, VCM1, VCM0 - // LCD_Write_COM_DATA(0x01,0x2B3F); // driver control output REV, BGR, TB, MUX8, MUX5, MUX4, MUX3, MUX2, MUX1, MUX0 - - // This sets the direction of the scan. These two are mirror - // opposites. The first is right in my setup. - LCD_Write_COM_DATA(0x01,0x293F); // driver control output REV, BGR, TB, MUX8, MUX5, MUX4, MUX3, MUX2, MUX1, MUX0 - // LCD_Write_COM_DATA(0x01,0x693F); // driver control output RL, REV, BGR, TB, MUX8, MUX5, MUX4, MUX3, MUX2, MUX1, MUX0 - - - LCD_Write_COM_DATA(0x02,0x0600); // LCD drive AC control B/C, EOR - LCD_Write_COM_DATA(0x10,0x0000); // sleep mode 0 - // Change the (Y) order here to match above (TB=0) - //LCD_Write_COM_DATA(0x11,0x6070); // Entry mode DFM1, DFM0, TY0, ID1, ID0 - //LCD_Write_COM_DATA(0x11,0x6050); // Entry mode DFM1, DFM0, TY0, ID0 - LCD_Write_COM_DATA(0x11,0x6078); // Entry mode DFM1, DFM0, TY0, ID1, ID0, AM - - LCD_Write_COM_DATA(0x05,0x0000); // compare reg1 - LCD_Write_COM_DATA(0x06,0x0000); // compare reg2 - LCD_Write_COM_DATA(0x16,0xEF1C); // horiz porch (default) - LCD_Write_COM_DATA(0x17,0x0003); // vertical porch - LCD_Write_COM_DATA(0x07,0x0233); // display control VLE1, GON, DTE, D1, D0 - LCD_Write_COM_DATA(0x0B,0x5308); // frame cycle control: %0101 0011 0000 1000 - - LCD_Write_COM_DATA(0x0F,0x0000); // gate scan start posn - LCD_Write_COM_DATA(0x41,0x0000); // vertical scroll control1 - LCD_Write_COM_DATA(0x42,0x0000); // vertical scroll control2 - LCD_Write_COM_DATA(0x48,0x0000); // first window start - LCD_Write_COM_DATA(0x49,0x013F); // first window end (0x13f == 319) - LCD_Write_COM_DATA(0x4A,0x0000); // second window start - LCD_Write_COM_DATA(0x4B,0x0000); // second window end - LCD_Write_COM_DATA(0x44,0xEF00); // horiz ram addr posn - LCD_Write_COM_DATA(0x45,0x0000); // vert ram start posn - LCD_Write_COM_DATA(0x46,0x013F); // vert ram end posn - LCD_Write_COM_DATA(0x30,0x0707); // γ control - LCD_Write_COM_DATA(0x31,0x0204);// - LCD_Write_COM_DATA(0x32,0x0204);// - LCD_Write_COM_DATA(0x33,0x0502);// - LCD_Write_COM_DATA(0x34,0x0507);// - LCD_Write_COM_DATA(0x35,0x0204);// - LCD_Write_COM_DATA(0x36,0x0204);// - LCD_Write_COM_DATA(0x37,0x0502);// - LCD_Write_COM_DATA(0x3A,0x0302);// - LCD_Write_COM_DATA(0x3B,0x0302);// - LCD_Write_COM_DATA(0x23,0x0000);// RAM write data mask1 - LCD_Write_COM_DATA(0x24,0x0000); // RAM write data mask2 - LCD_Write_COM_DATA(0x25,0x8000); // frame frequency (OSC3) - LCD_Write_COM_DATA(0x4f,0x0000); // Set GDDRAM Y address counter - LCD_Write_COM_DATA(0x4e,0x0000); // Set GDDRAM X address counter -#if 1 - // Set data access speed optimization (?) per pg. 50; doesn't actually seem to change anything though? - LCD_Write_COM_DATA(0x28, 0x0006); - LCD_Write_COM_DATA(0x2F, 0x12BE); - LCD_Write_COM_DATA(0x12, 0x6CEB); -#endif - - LCD_Write_COM(0x22); // RAM data write - sbi(P_CS, B_CS); + tft.begin(); + tft.setRotation(3); + tft.setClock(_clock); + // Could set up an automatic DMA transfer here; cf. + // https://forum.pjrc.com/threads/25778-Could-there-be-something-like-an-ISR-template-function/page4 + // LCD initialization complete - setColor(255, 255, 255); - clrScr(); driveIndicator[0] = driveIndicator[1] = false; @@ -216,196 +99,37 @@ TeensyDisplay::~TeensyDisplay() { } -void TeensyDisplay::_fast_fill_16(int ch, int cl, long pix) -{ - *(volatile uint8_t *)(&GPIOD_PDOR) = ch; - *(volatile uint8_t *)(&GPIOC_PDOR) = cl; - uint16_t blocks = pix / 16; - - for (uint16_t i=0; idrawStaticUIElement(UIeOverlay); if (g_vm) { g_ui->drawOnOffUIElement(UIeDisk1_state, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0'); g_ui->drawOnOffUIElement(UIeDisk2_state, ((AppleVM *)g_vm)->DiskName(1)[0] == '\0'); } - - cbi(P_CS, B_CS); - clrXY(); - sbi(P_RS, B_RS); } void TeensyDisplay::clrScr() { - cbi(P_CS, B_CS); - clrXY(); - sbi(P_RS, B_RS); - _fast_fill_16(0, 0, ((disp_x_size+1)*(disp_y_size+1))); - sbi(P_CS, B_CS); -} - -// The display flips X and Y, so expect to see "x" as "vertical" -// and "y" as "horizontal" here... -void TeensyDisplay::setYX(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) -{ - LCD_Write_COM_DATA(0x44, (y2<<8)+y1); // Horiz start addr, Horiz end addr - LCD_Write_COM_DATA(0x45, x1); // vert start pos - LCD_Write_COM_DATA(0x46, x2); // vert end pos - LCD_Write_COM_DATA(0x4e,y1); // RAM address set (horiz) - LCD_Write_COM_DATA(0x4f,x1); // RAM address set (vert) - LCD_Write_COM(0x22); -} - -void TeensyDisplay::clrXY() -{ - setYX(0, 0, disp_y_size, disp_x_size); -} - -void TeensyDisplay::setColor(byte r, byte g, byte b) -{ - fch=((r&248)|g>>5); - fcl=((g&28)<<3|b>>3); -} - -void TeensyDisplay::setColor(uint16_t color) -{ - fch = (uint8_t)(color >> 8); - fcl = (uint8_t)(color & 0xFF); -} - -void TeensyDisplay::fillRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) -{ - if (x1>x2) { - swap(uint16_t, x1, x2); - } - if (y1 > y2) { - swap(uint16_t, y1, y2); - } - - cbi(P_CS, B_CS); - setYX(x1, y1, x2, y2); - sbi(P_RS, B_RS); - _fast_fill_16(fch,fcl,((long(x2-x1)+1)*(long(y2-y1)+1))); - sbi(P_CS, B_CS); -} - -void TeensyDisplay::drawPixel(uint16_t x, uint16_t y) -{ - cbi(P_CS, B_CS); - setYX(x, y, x, y); - setPixel((fch<<8)|fcl); - sbi(P_CS, B_CS); - clrXY(); + // FIXME: only fill the area that's got our "terminal" + tft.fillScreen(ILI9341_BLACK); } void TeensyDisplay::drawUIPixel(uint16_t x, uint16_t y, uint16_t color) { - drawPixel(x,y,color); + tft.drawPixel(x,y,color); } void TeensyDisplay::drawPixel(uint16_t x, uint16_t y, uint16_t color) { - cbi(P_CS, B_CS); - setYX(x, y, x, y); - setPixel(color); - sbi(P_CS, B_CS); - clrXY(); + tft.drawPixel(x,y,color); } void TeensyDisplay::drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b) { uint16_t color16 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3); - cbi(P_CS, B_CS); - setYX(x, y, x, y); - setPixel(color16); - sbi(P_CS, B_CS); - clrXY(); -} - -void TeensyDisplay::LCD_Writ_Bus(uint8_t ch, uint8_t cl) -{ - *(volatile uint8_t *)(&GPIOD_PDOR) = ch; - *(volatile uint8_t *)(&GPIOC_PDOR) = cl; - pulse_low(P_WR, B_WR); -} - -void TeensyDisplay::LCD_Write_COM(uint8_t VL) -{ - cbi(P_RS, B_RS); - LCD_Writ_Bus(0x00, VL); -} - -void TeensyDisplay::LCD_Write_DATA(uint8_t VH, uint8_t VL) -{ - sbi(P_RS, B_RS); - LCD_Writ_Bus(VH,VL); -} - -void TeensyDisplay::LCD_Write_DATA(uint8_t VL) -{ - sbi(P_RS, B_RS); - LCD_Writ_Bus(0x00, VL); -} - -void TeensyDisplay::LCD_Write_COM_DATA(uint8_t com1, uint16_t dat1) -{ - LCD_Write_COM(com1); - LCD_Write_DATA(dat1>>8, dat1); -} - -void TeensyDisplay::moveTo(uint16_t col, uint16_t row) -{ - cbi(P_CS, B_CS); - - // FIXME: eventually set drawing to the whole screen and leave it that way - - // set drawing to the whole screen - // setYX(0, 0, disp_y_size, disp_x_size); - LCD_Write_COM_DATA(0x4e,row); // RAM address set (horiz) - LCD_Write_COM_DATA(0x4f,col); // RAM address set (vert) - - LCD_Write_COM(0x22); -} - -void TeensyDisplay::drawNextPixel(uint16_t color) -{ - // Anything inside this object should call setPixel directly. This - // is primarily for the BIOS. - setPixel(color); + drawPixel(x,y,color16); } void TeensyDisplay::blit(AiieRect r) @@ -413,20 +137,7 @@ void TeensyDisplay::blit(AiieRect r) // remember these are "starts at pixel number" values, where 0 is the first. #define HOFFSET 18 #define VOFFSET 13 - - // Define the horizontal area that we're going to draw in - LCD_Write_COM_DATA(0x45, HOFFSET+r.left); // offset by 20 to center it... - LCD_Write_COM_DATA(0x46, HOFFSET+r.right); - - // position the "write" address - LCD_Write_COM_DATA(0x4e,VOFFSET+r.top); // row - LCD_Write_COM_DATA(0x4f,HOFFSET+r.left); // col - - // prepare the LCD to receive data bytes for its RAM - LCD_Write_COM(0x22); - - // send the pixel data - sbi(P_RS, B_RS); + uint8_t *vbufPtr; for (uint8_t y=r.top; y<=r.bottom; y++) { vbufPtr = &videoBuffer[y * TEENSY_DRUN + r.left]; @@ -440,19 +151,17 @@ void TeensyDisplay::blit(AiieRect r) } colorIdx <<= 1; - // The colors are broken up in to two 8-bit values to speed things up. - const uint8_t *p; - + uint16_t c; if (g_displayType == m_monochrome) { - p = &loresPixelColorsGreen[colorIdx]; + c = loresPixelColorsGreen[colorIdx]; } else if (g_displayType == m_blackAndWhite) { - p = &loresPixelColorsWhite[colorIdx]; + c = loresPixelColorsWhite[colorIdx]; } else { - p = &loresPixelColors[colorIdx]; + c = loresPixelColors[colorIdx]; } - LCD_Writ_Bus(*p, *(p+1)); + drawPixel(x+HOFFSET,y+VOFFSET,c); if (x & 0x01) { // When we do the odd pixels, then move the pixel pointer to the next pixel @@ -460,14 +169,9 @@ void TeensyDisplay::blit(AiieRect r) } } } - cbi(P_CS, B_CS); // draw overlay, if any if (overlayMessage[0]) { - // reset the viewport in order to draw the overlay... - LCD_Write_COM_DATA(0x45, 0); - LCD_Write_COM_DATA(0x46, 319); - drawString(M_SELECTDISABLED, 1, 240 - 16 - 12, overlayMessage); } } @@ -504,30 +208,17 @@ void TeensyDisplay::drawCharacter(uint8_t mode, uint16_t x, uint8_t y, char c) temp=(c*ysize); - // FIXME: the embedded moveTo() and setPixel() calls *should* work - // -- and do, for the most part. But in the BIOS they cut off after - // about half the screen. Using drawPixel() is substantially less - // efficient, but works properly. - for (int8_t y_off = 0; y_off <= ysize; y_off++) { - //moveTo(x, y + y_off); // does a cbi(P_CS, B_CS) uint8_t ch = pgm_read_byte(&BiosFont[temp]); for (int8_t x_off = 0; x_off <= xsize; x_off++) { if (ch & (1 << (7-x_off))) { drawPixel(x+x_off, y+y_off, onPixel); - //setPixel(onPixel); } else { drawPixel(x+x_off, y+y_off, offPixel); - //setPixel(offPixel); } } temp++; } - - // Need to leave cbi set for the next draw operation. Particularly important - // on startup, when transitioning from '@' to 'Apple //e', while also drawing - // overlay text. - cbi(P_CS, B_CS); } void TeensyDisplay::drawString(uint8_t mode, uint16_t x, uint8_t y, const char *str) @@ -546,19 +237,12 @@ void TeensyDisplay::drawImageOfSizeAt(const uint8_t *img, { uint8_t r, g, b; - if (sizex == DISPLAYWIDTH) { - moveTo(0,0); - } - for (uint8_t y=0; y>5) << 8) | ((g&28)<<3|b>>3)); + drawPixel(wherex+x, wherey+y, (((r&248)|g>>5) << 8) | ((g&28)<<3|b>>3)); } } } @@ -616,4 +300,3 @@ void TeensyDisplay::cachePixel(uint16_t x, uint16_t y, uint8_t color) cacheDoubleWidePixel(x/2, y, color); } } - diff --git a/teensy/teensy-display.h b/teensy/teensy-display.h index 0d09be2..7eed5d8 100644 --- a/teensy/teensy-display.h +++ b/teensy/teensy-display.h @@ -2,6 +2,7 @@ #define __TEENSY_DISPLAY_H #include +#include #include "physicaldisplay.h" #define TEENSY_DHEIGHT 192 @@ -12,16 +13,6 @@ #define regtype volatile uint8_t #define regsize uint8_t -#define cbi(reg, bitmask) *reg &= ~bitmask -#define sbi(reg, bitmask) *reg |= bitmask -#define pulse_high(reg, bitmask) { sbi(reg, bitmask); cbi(reg, bitmask); } -#define pulse_low(reg, bitmask) { cbi(reg, bitmask); sbi(reg, bitmask); } - -#define cport(port, data) port &= data -#define sport(port, data) port |= data - -#define swap(type, i, j) {type t = i; i = j; j = t;} - class UTFT; class BIOS; @@ -47,40 +38,15 @@ class TeensyDisplay : public PhysicalDisplay { virtual void cache2DoubleWidePixels(uint16_t x, uint16_t y, uint8_t colorA, uint8_t colorB); virtual void cachePixel(uint16_t x, uint16_t y, uint8_t color); - protected: - void moveTo(uint16_t col, uint16_t row); - void drawNextPixel(uint16_t color); - private: - regtype *P_RS, *P_WR, *P_CS, *P_RST, *P_SDA, *P_SCL, *P_ALE; - regsize B_RS, B_WR, B_CS, B_RST, B_SDA, B_SCL, B_ALE; - - uint8_t fch, fcl; // high and low foreground colors - - void _fast_fill_16(int ch, int cl, long pix); - - void setYX(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); - void clrXY(); - - void setColor(byte r, byte g, byte b); - void setColor(uint16_t color); - void fillRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); - virtual void drawPixel(uint16_t x, uint16_t y); virtual void drawPixel(uint16_t x, uint16_t y, uint16_t color); virtual void drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b); virtual void drawUIPixel(uint16_t x, uint16_t y, uint16_t color); - inline void LCD_Writ_Bus(uint8_t VH,uint8_t VL) __attribute__((always_inline)); - inline void LCD_Write_COM(uint8_t VL) __attribute__((always_inline)); - inline void LCD_Write_DATA(uint8_t VH,uint8_t VL) __attribute__((always_inline)); - inline void LCD_Write_DATA(uint8_t VL) __attribute__((always_inline)); - inline void LCD_Write_COM_DATA(uint8_t com1,uint16_t dat1) __attribute__((always_inline)); - bool needsRedraw; bool driveIndicator[2]; bool driveIndicatorDirty; - // video buffer is 4bpp uint8_t videoBuffer[TEENSY_DHEIGHT * TEENSY_DWIDTH / 2]; }; diff --git a/teensy/teensy-filemanager.cpp b/teensy/teensy-filemanager.cpp index 4197745..cca771d 100644 --- a/teensy/teensy-filemanager.cpp +++ b/teensy/teensy-filemanager.cpp @@ -1,6 +1,5 @@ #include #include -#include #include "teensy-filemanager.h" #include // strcpy #include @@ -15,7 +14,7 @@ TeensyFileManager::TeensyFileManager() // FIXME: used to have 'enabled = sd.begin()' here, but we weren't // using the enabled flag, so I've removed it to save the RAM for // now; but eventually we need better error handling here - sd.begin(); + SD.begin(BUILTIN_SDCARD); } TeensyFileManager::~TeensyFileManager() @@ -94,7 +93,7 @@ int8_t TeensyFileManager::readDir(const char *where, const char *suffix, char *o } int8_t idxCount = 1; - File f = sd.open(where); + File f = SD.open(where, FILE_READ); while (1) { File e = f.openNextFile(); @@ -105,7 +104,8 @@ int8_t TeensyFileManager::readDir(const char *where, const char *suffix, char *o } // Skip MAC fork files - e.getName(outputFN, maxlen-1); // -1 for trailing '/' on directories + // FIXME: strncpy + strcpy(outputFN, e.name()); // and we need maxlen-1 for trailing '/' on directories if (outputFN[0] == '.') { e.close(); continue; @@ -166,8 +166,8 @@ bool TeensyFileManager::_prepCache(int8_t fd) } // Open the new one - cacheFile = sd.open(cachedNames[fd], O_RDWR | O_CREAT); - if (!cacheFile.isOpen()) { + cacheFile = SD.open(cachedNames[fd], FILE_WRITE); + if (!cacheFile) { return false; } cacheFd = fd; // cache is live @@ -198,12 +198,12 @@ bool TeensyFileManager::setSeekPosition(int8_t fd, uint32_t pos) // FIXME: this should be private void TeensyFileManager::seekToEnd(int8_t fd) { - FatFile f = sd.open(cachedNames[fd], FILE_READ); - if (!f.isOpen()) { + File f = SD.open(cachedNames[fd], FILE_READ); + if (!f) { return; } - fileSeekPositions[fd] = f.fileSize(); + fileSeekPositions[fd] = f.size(); f.close(); } @@ -223,11 +223,11 @@ int TeensyFileManager::write(int8_t fd, const void *buf, int nbyte) uint32_t pos = fileSeekPositions[fd]; - if (!cacheFile.seekSet(pos)) { + if (!cacheFile.seek(pos)) { return -1; } - if (cacheFile.write(buf, nbyte) != nbyte) { + if (cacheFile.write((const uint8_t *)buf, (size_t)nbyte) != (size_t)nbyte) { return -1; } @@ -251,7 +251,7 @@ int TeensyFileManager::read(int8_t fd, void *buf, int nbyte) _prepCache(fd); uint32_t pos = fileSeekPositions[fd]; - if (!cacheFile.seekSet(pos)) { + if (!cacheFile.seek(pos)) { return -1; } fileSeekPositions[fd] += nbyte; diff --git a/teensy/teensy-filemanager.h b/teensy/teensy-filemanager.h index 0367fea..2f580af 100644 --- a/teensy/teensy-filemanager.h +++ b/teensy/teensy-filemanager.h @@ -3,7 +3,8 @@ #include "filemanager.h" #include -#include +#include +#include class TeensyFileManager : public FileManager { public: @@ -30,11 +31,10 @@ class TeensyFileManager : public FileManager { bool _prepCache(int8_t fd); private: - volatile int8_t numCached; + int8_t numCached; - volatile SdFatSdio sd; - volatile int8_t cacheFd; - volatile FatFile cacheFile; + int8_t cacheFd; + File cacheFile; }; #endif diff --git a/teensy/teensy-speaker.cpp b/teensy/teensy-speaker.cpp index 729774a..6bc1d02 100644 --- a/teensy/teensy-speaker.cpp +++ b/teensy/teensy-speaker.cpp @@ -23,7 +23,8 @@ void TeensySpeaker::toggle(uint32_t c) mixerValue >>= (16-g_volume); // FIXME: glad it's DAC0 and all, but... how does that relate to the pin passed in the constructor? - analogWriteDAC0(mixerValue); + // FIXME: really doesn't work for the Teensy 4 at all + // analogWriteDAC0(mixerValue); } void TeensySpeaker::maintainSpeaker(uint32_t c, uint64_t runtimeInMicros) diff --git a/teensy/teensy.ino b/teensy/teensy.ino index cb01959..356799e 100644 --- a/teensy/teensy.ino +++ b/teensy/teensy.ino @@ -20,7 +20,7 @@ #define RESETPIN 39 #define BATTERYPIN 32 -#define SPEAKERPIN A21 +#define SPEAKERPIN 19 // FIXME this isn't right #include "globals.h" #include "teensy-crash.h" @@ -35,13 +35,6 @@ BIOS bios; static time_t getTeensy3Time() { return Teensy3Clock.get(); } -#define ESP_TXD 51 -#define ESP_CHPD 52 -#define ESP_RST 53 -#define ESP_RXD 40 -#define ESP_GPIO0 41 -#define ESP_GPIO2 42 - void setup() { Serial.begin(230400); @@ -65,6 +58,8 @@ void setup() pinMode(RESETPIN, INPUT); digitalWrite(RESETPIN, HIGH); + println("FIXME: skipping analogReference, speaker, battery for Teensy 4"); + /* analogReference(EXTERNAL); // 3.3v external, or 1.7v internal. We need 1.7 internal for the battery level, which means we're gonna have to do something about the paddles :/ analogReadRes(8); // We only need 8 bits of resolution (0-255) for battery & paddles analogReadAveraging(4); // ?? dunno if we need this or not. @@ -72,6 +67,7 @@ void setup() pinMode(SPEAKERPIN, OUTPUT); // analog speaker output, used as digital volume control pinMode(BATTERYPIN, INPUT); + */ println("creating virtual hardware"); g_speaker = new TeensySpeaker(SPEAKERPIN); @@ -111,7 +107,7 @@ void setup() g_keyboard = new TeensyKeyboard(g_vm->getKeyboard()); println(" paddles"); - g_paddles = new TeensyPaddles(A23, A24, 1, 1); + g_paddles = new TeensyPaddles(A3, A4, 1, 1); // Now that all the virtual hardware is glued together, reset the VM println("Resetting VM"); @@ -293,9 +289,12 @@ void loop() // This is a bit disruptive - but the external 3.3v will drop along with the battery level, so we should use the more stable (I hope) internal 1.7v. // The alternative is to build a more stable buck/boost regulator for reference... + + println("FIXME: analogReference for Teensy 4.0 => batteryLevel"); + /* analogReference(INTERNAL); batteryLevel = analogRead(BATTERYPIN); - analogReference(EXTERNAL); + analogReference(EXTERNAL);*/ /* LiIon charge to a max of 4.2v; and we should not let them discharge below about 3.5v. * With a resistor voltage divider of Z1=39k, Z2=10k we're looking at roughly 20.4% of