mirror of
https://github.com/JorjBauer/aiie.git
synced 2024-11-16 21:06:38 +00:00
first pass at Teensy 4.1 support
This commit is contained in:
parent
e8b77c8aff
commit
c9fe8edc29
@ -2,7 +2,9 @@
|
|||||||
#define __NIBUTIL_H
|
#define __NIBUTIL_H
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#ifndef TEENSYDUINO
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -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<sizeof(addrPins); i++) {
|
|
||||||
pinMode(addrPins[i], INPUT); // disable pull-ups
|
|
||||||
pinMode(addrPins[i], OUTPUT);
|
|
||||||
digitalWrite(addrPins[i], LOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParallelSRAM::SetPins()
|
|
||||||
{
|
|
||||||
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<sizeof(addrPins); i++) {
|
|
||||||
pinMode(addrPins[i], INPUT); // disable pull-ups
|
|
||||||
pinMode(addrPins[i], OUTPUT);
|
|
||||||
digitalWrite(addrPins[i], LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ParallelSRAM::~ParallelSRAM()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ParallelSRAM::read(uint32_t addr)
|
|
||||||
{
|
|
||||||
cli();
|
|
||||||
// Read cycle 2
|
|
||||||
setAddress(addr);
|
|
||||||
|
|
||||||
// make sure address is valid before CE is asserted
|
|
||||||
DELAY;
|
|
||||||
|
|
||||||
CE_ON;
|
|
||||||
OE_ON;
|
|
||||||
|
|
||||||
DELAY;
|
|
||||||
|
|
||||||
uint8_t ret = getInput();
|
|
||||||
|
|
||||||
// Optional; can leave these lines asserted...
|
|
||||||
OE_OFF;
|
|
||||||
CE_OFF;
|
|
||||||
|
|
||||||
sei();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParallelSRAM::write(uint32_t addr, uint8_t v)
|
|
||||||
{
|
|
||||||
cli();
|
|
||||||
setAddress(addr);
|
|
||||||
|
|
||||||
DELAY;
|
|
||||||
|
|
||||||
WE_ON;
|
|
||||||
CE_ON;
|
|
||||||
|
|
||||||
setOutput(v);
|
|
||||||
|
|
||||||
DELAY;
|
|
||||||
|
|
||||||
CE_OFF;
|
|
||||||
WE_OFF;
|
|
||||||
sei();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ParallelSRAM::getInput()
|
|
||||||
{
|
|
||||||
if (!isInput) {
|
|
||||||
#if 1
|
|
||||||
// Directly set the direction bits. The rest of the port setup
|
|
||||||
// should be fine from the initial config.
|
|
||||||
*(volatile uint8_t *)(&GPIOD_PDDR) = 0x00; // inputs
|
|
||||||
#else
|
|
||||||
pinMode(2, INPUT);
|
|
||||||
pinMode(14, INPUT);
|
|
||||||
pinMode(7, INPUT);
|
|
||||||
pinMode(8, INPUT);
|
|
||||||
pinMode(6, INPUT);
|
|
||||||
pinMode(20, INPUT);
|
|
||||||
pinMode(21, INPUT);
|
|
||||||
pinMode(5, INPUT);
|
|
||||||
#endif
|
|
||||||
isInput = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GPIOD_PDIR & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParallelSRAM::setOutput(uint8_t v)
|
|
||||||
{
|
|
||||||
// FIXME: is there a faster way to do this?
|
|
||||||
if (isInput) {
|
|
||||||
#if 1
|
|
||||||
// FIMXE: would this be correct?
|
|
||||||
*(volatile uint8_t *)(&GPIOD_PDDR) |= 0xFF; // outputs
|
|
||||||
#else
|
|
||||||
pinMode(2, OUTPUT);
|
|
||||||
pinMode(14, OUTPUT);
|
|
||||||
pinMode(7, OUTPUT);
|
|
||||||
pinMode(8, OUTPUT);
|
|
||||||
pinMode(6, OUTPUT);
|
|
||||||
pinMode(20, OUTPUT);
|
|
||||||
pinMode(21, OUTPUT);
|
|
||||||
pinMode(5, OUTPUT);
|
|
||||||
#endif
|
|
||||||
isInput = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Directly set the low 8 bits of D.
|
|
||||||
*(volatile uint8_t *)(&GPIOD_PDOR) = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParallelSRAM::setAddress(uint32_t addr)
|
|
||||||
{
|
|
||||||
// The low 12 bits of the address go right in to Port C. Set these
|
|
||||||
// by doing a clear of the bitmask, and then set the bits...
|
|
||||||
GPIOC_PCOR = 0x00000FFF;
|
|
||||||
GPIOC_PSOR = (addr & 0xFFF);
|
|
||||||
|
|
||||||
// The high 6 bits of the address go in to Port B, bits 0..5.
|
|
||||||
// We do that the same way...
|
|
||||||
GPIOB_PCOR = 0x0000003F;
|
|
||||||
GPIOB_PSOR = (addr >> 12);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
for (uint8_t i=0; i<sizeof(addrPins); i++) {
|
|
||||||
digitalWrite(addrPins[i],
|
|
||||||
addr & (1 << i) ? HIGH : LOW);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
#ifndef __PARALLELSRAM_H
|
|
||||||
#define __PARALLELSRAM_H
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
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
|
|
@ -4,208 +4,91 @@
|
|||||||
#include "bios-font.h"
|
#include "bios-font.h"
|
||||||
#include "appleui.h"
|
#include "appleui.h"
|
||||||
|
|
||||||
#define RS 16
|
#define _clock 65000000
|
||||||
#define WR 17
|
|
||||||
#define CS 18
|
|
||||||
#define RST 19
|
|
||||||
|
|
||||||
// Ports C&D of the Teensy connected to DB of the display
|
#define PIN_RST 8
|
||||||
#define DB_0 15
|
#define PIN_DC 9
|
||||||
#define DB_1 22
|
#define PIN_CS 10
|
||||||
#define DB_2 23
|
#define PIN_MOSI 11
|
||||||
#define DB_3 9
|
#define PIN_MISO 12
|
||||||
#define DB_4 10
|
#define PIN_SCK 13
|
||||||
#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 disp_x_size 239
|
#define disp_x_size 239
|
||||||
#define disp_y_size 319
|
#define disp_y_size 319
|
||||||
|
|
||||||
#define setPixel(color) { LCD_Write_DATA(((color)>>8),((color)&0xFF)); } // 565 RGB
|
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "applevm.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
|
// RGB map of each of the lowres colors
|
||||||
const uint8_t loresPixelColors[16*2] = { 0x00,0x00, // 0 black
|
const uint16_t loresPixelColors[16] = { 0x0000, // 0 black
|
||||||
0xC0,0x06, // 1 magenta
|
0xC006, // 1 magenta
|
||||||
0x00,0x10, // 2 dark blue
|
0x0010, // 2 dark blue
|
||||||
0xA1,0xB5, // 3 purple
|
0xA1B5, // 3 purple
|
||||||
0x04,0x80, // 4 dark green
|
0x0480, // 4 dark green
|
||||||
0x6B,0x4D, // 5 dark grey
|
0x6B4D, // 5 dark grey
|
||||||
0x1B,0x9F, // 6 med blue
|
0x1B9F, // 6 med blue
|
||||||
0x0D,0xFD, // 7 light blue
|
0x0DFD, // 7 light blue
|
||||||
0x92,0xA5, // 8 brown
|
0x92A5, // 8 brown
|
||||||
0xF8,0xC5, // 9 orange
|
0xF8C5, // 9 orange
|
||||||
0x95,0x55, // 10 light gray
|
0x9555, // 10 light gray
|
||||||
0xFC,0xF2, // 11 pink
|
0xFCF2, // 11 pink
|
||||||
0x07,0xE0, // 12 green
|
0x07E0, // 12 green
|
||||||
0xFF,0xE0, // 13 yellow
|
0xFFE0, // 13 yellow
|
||||||
0x87,0xF0, // 14 aqua
|
0x87F0, // 14 aqua
|
||||||
0xFF,0xFF // 15 white
|
0xFFFF // 15 white
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t loresPixelColorsGreen[16*2] = { 0x00, 0x00,
|
const uint16_t loresPixelColorsGreen[16] = { 0x0000,
|
||||||
0x01, 0x40,
|
0x0140,
|
||||||
0x00, 0x40,
|
0x0040,
|
||||||
0x02, 0x80,
|
0x0280,
|
||||||
0x03, 0x00,
|
0x0300,
|
||||||
0x03, 0x40,
|
0x0340,
|
||||||
0x03, 0x00,
|
0x0300,
|
||||||
0x04, 0x80,
|
0x0480,
|
||||||
0x02, 0xC0,
|
0x02C0,
|
||||||
0x02, 0x40,
|
0x0240,
|
||||||
0x05, 0x00,
|
0x0500,
|
||||||
0x05, 0x40,
|
0x0540,
|
||||||
0x05, 0x80,
|
0x0580,
|
||||||
0x07, 0x00,
|
0x0700,
|
||||||
0x06, 0x80,
|
0x0680,
|
||||||
0x07, 0xC0
|
0x07C0
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t loresPixelColorsWhite[16*2] = { 0x00, 0x00,
|
const uint16_t loresPixelColorsWhite[16] = { 0x0000,
|
||||||
0x29, 0x45,
|
0x2945,
|
||||||
0x08, 0x41,
|
0x0841,
|
||||||
0x52, 0x8A,
|
0x528A,
|
||||||
0x63, 0x0C,
|
0x630C,
|
||||||
0x6B, 0x4D,
|
0x6B4D,
|
||||||
0x63, 0x0C,
|
0x630C,
|
||||||
0x94, 0x92,
|
0x9492,
|
||||||
0x5A, 0xCB,
|
0x5ACB,
|
||||||
0x4A, 0x49,
|
0x4A49,
|
||||||
0xA5, 0x14,
|
0xA514,
|
||||||
0xAD, 0x55,
|
0xAD55,
|
||||||
0xB5, 0x96,
|
0xB596,
|
||||||
0xE7, 0x1C,
|
0xE71C,
|
||||||
0xD6, 0x9A,
|
0xD69A,
|
||||||
0xFF, 0xDF
|
0xFFDF
|
||||||
};
|
};
|
||||||
|
|
||||||
TeensyDisplay::TeensyDisplay()
|
TeensyDisplay::TeensyDisplay()
|
||||||
{
|
{
|
||||||
memset(videoBuffer, 0, sizeof(videoBuffer));
|
memset(videoBuffer, 0, sizeof(videoBuffer));
|
||||||
|
|
||||||
pinMode(DB_8, OUTPUT);
|
tft.begin();
|
||||||
pinMode(DB_9, OUTPUT);
|
tft.setRotation(3);
|
||||||
pinMode(DB_10, OUTPUT);
|
tft.setClock(_clock);
|
||||||
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));
|
// Could set up an automatic DMA transfer here; cf.
|
||||||
B_RS = digitalPinToBitMask(RS);
|
// https://forum.pjrc.com/threads/25778-Could-there-be-something-like-an-ISR-template-function/page4
|
||||||
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);
|
|
||||||
|
|
||||||
// LCD initialization complete
|
// LCD initialization complete
|
||||||
|
|
||||||
setColor(255, 255, 255);
|
|
||||||
|
|
||||||
clrScr();
|
clrScr();
|
||||||
|
|
||||||
driveIndicator[0] = driveIndicator[1] = false;
|
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; i<blocks; i++) {
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
}
|
|
||||||
if ((pix % 16) != 0) {
|
|
||||||
for (int i=0; i<(pix % 16); i++)
|
|
||||||
{
|
|
||||||
pulse_low(P_WR, B_WR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TeensyDisplay::redraw()
|
void TeensyDisplay::redraw()
|
||||||
{
|
{
|
||||||
cbi(P_CS, B_CS);
|
|
||||||
clrXY();
|
|
||||||
sbi(P_RS, B_RS);
|
|
||||||
|
|
||||||
moveTo(0, 0);
|
|
||||||
|
|
||||||
g_ui->drawStaticUIElement(UIeOverlay);
|
g_ui->drawStaticUIElement(UIeOverlay);
|
||||||
|
|
||||||
if (g_vm) {
|
if (g_vm) {
|
||||||
g_ui->drawOnOffUIElement(UIeDisk1_state, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
|
g_ui->drawOnOffUIElement(UIeDisk1_state, ((AppleVM *)g_vm)->DiskName(0)[0] == '\0');
|
||||||
g_ui->drawOnOffUIElement(UIeDisk2_state, ((AppleVM *)g_vm)->DiskName(1)[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()
|
void TeensyDisplay::clrScr()
|
||||||
{
|
{
|
||||||
cbi(P_CS, B_CS);
|
// FIXME: only fill the area that's got our "terminal"
|
||||||
clrXY();
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TeensyDisplay::drawUIPixel(uint16_t x, uint16_t y, uint16_t color)
|
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)
|
void TeensyDisplay::drawPixel(uint16_t x, uint16_t y, uint16_t color)
|
||||||
{
|
{
|
||||||
cbi(P_CS, B_CS);
|
tft.drawPixel(x,y,color);
|
||||||
setYX(x, y, x, y);
|
|
||||||
setPixel(color);
|
|
||||||
sbi(P_CS, B_CS);
|
|
||||||
clrXY();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TeensyDisplay::drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b)
|
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);
|
uint16_t color16 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
|
||||||
|
|
||||||
cbi(P_CS, B_CS);
|
drawPixel(x,y,color16);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TeensyDisplay::blit(AiieRect r)
|
void TeensyDisplay::blit(AiieRect r)
|
||||||
@ -414,19 +138,6 @@ void TeensyDisplay::blit(AiieRect r)
|
|||||||
#define HOFFSET 18
|
#define HOFFSET 18
|
||||||
#define VOFFSET 13
|
#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;
|
uint8_t *vbufPtr;
|
||||||
for (uint8_t y=r.top; y<=r.bottom; y++) {
|
for (uint8_t y=r.top; y<=r.bottom; y++) {
|
||||||
vbufPtr = &videoBuffer[y * TEENSY_DRUN + r.left];
|
vbufPtr = &videoBuffer[y * TEENSY_DRUN + r.left];
|
||||||
@ -440,19 +151,17 @@ void TeensyDisplay::blit(AiieRect r)
|
|||||||
}
|
}
|
||||||
colorIdx <<= 1;
|
colorIdx <<= 1;
|
||||||
|
|
||||||
// The colors are broken up in to two 8-bit values to speed things up.
|
uint16_t c;
|
||||||
const uint8_t *p;
|
|
||||||
|
|
||||||
if (g_displayType == m_monochrome) {
|
if (g_displayType == m_monochrome) {
|
||||||
p = &loresPixelColorsGreen[colorIdx];
|
c = loresPixelColorsGreen[colorIdx];
|
||||||
}
|
}
|
||||||
else if (g_displayType == m_blackAndWhite) {
|
else if (g_displayType == m_blackAndWhite) {
|
||||||
p = &loresPixelColorsWhite[colorIdx];
|
c = loresPixelColorsWhite[colorIdx];
|
||||||
} else {
|
} else {
|
||||||
p = &loresPixelColors[colorIdx];
|
c = loresPixelColors[colorIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
LCD_Writ_Bus(*p, *(p+1));
|
drawPixel(x+HOFFSET,y+VOFFSET,c);
|
||||||
|
|
||||||
if (x & 0x01) {
|
if (x & 0x01) {
|
||||||
// When we do the odd pixels, then move the pixel pointer to the next pixel
|
// 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
|
// draw overlay, if any
|
||||||
if (overlayMessage[0]) {
|
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);
|
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);
|
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++) {
|
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]);
|
uint8_t ch = pgm_read_byte(&BiosFont[temp]);
|
||||||
for (int8_t x_off = 0; x_off <= xsize; x_off++) {
|
for (int8_t x_off = 0; x_off <= xsize; x_off++) {
|
||||||
if (ch & (1 << (7-x_off))) {
|
if (ch & (1 << (7-x_off))) {
|
||||||
drawPixel(x+x_off, y+y_off, onPixel);
|
drawPixel(x+x_off, y+y_off, onPixel);
|
||||||
//setPixel(onPixel);
|
|
||||||
} else {
|
} else {
|
||||||
drawPixel(x+x_off, y+y_off, offPixel);
|
drawPixel(x+x_off, y+y_off, offPixel);
|
||||||
//setPixel(offPixel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
temp++;
|
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)
|
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;
|
uint8_t r, g, b;
|
||||||
|
|
||||||
if (sizex == DISPLAYWIDTH) {
|
|
||||||
moveTo(0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t y=0; y<sizey; y++) {
|
for (uint8_t y=0; y<sizey; y++) {
|
||||||
if (sizex != DISPLAYWIDTH) {
|
|
||||||
moveTo(wherex, wherey + y);
|
|
||||||
}
|
|
||||||
for (uint16_t x=0; x<sizex; x++) {
|
for (uint16_t x=0; x<sizex; x++) {
|
||||||
r = pgm_read_byte(&img[(y*sizex + x)*3 + 0]);
|
r = pgm_read_byte(&img[(y*sizex + x)*3 + 0]);
|
||||||
g = pgm_read_byte(&img[(y*sizex + x)*3 + 1]);
|
g = pgm_read_byte(&img[(y*sizex + x)*3 + 1]);
|
||||||
b = pgm_read_byte(&img[(y*sizex + x)*3 + 2]);
|
b = pgm_read_byte(&img[(y*sizex + x)*3 + 2]);
|
||||||
setPixel((((r&248)|g>>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);
|
cacheDoubleWidePixel(x/2, y, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define __TEENSY_DISPLAY_H
|
#define __TEENSY_DISPLAY_H
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <ILI9341_t3.h>
|
||||||
#include "physicaldisplay.h"
|
#include "physicaldisplay.h"
|
||||||
|
|
||||||
#define TEENSY_DHEIGHT 192
|
#define TEENSY_DHEIGHT 192
|
||||||
@ -12,16 +13,6 @@
|
|||||||
#define regtype volatile uint8_t
|
#define regtype volatile uint8_t
|
||||||
#define regsize 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 UTFT;
|
||||||
class BIOS;
|
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 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);
|
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:
|
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, uint16_t color);
|
||||||
virtual void drawPixel(uint16_t x, uint16_t y, uint8_t r, uint8_t g, uint8_t b);
|
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);
|
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 needsRedraw;
|
||||||
bool driveIndicator[2];
|
bool driveIndicator[2];
|
||||||
bool driveIndicatorDirty;
|
bool driveIndicatorDirty;
|
||||||
|
|
||||||
// video buffer is 4bpp
|
|
||||||
uint8_t videoBuffer[TEENSY_DHEIGHT * TEENSY_DWIDTH / 2];
|
uint8_t videoBuffer[TEENSY_DHEIGHT * TEENSY_DWIDTH / 2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <SdFat.h>
|
|
||||||
#include "teensy-filemanager.h"
|
#include "teensy-filemanager.h"
|
||||||
#include <string.h> // strcpy
|
#include <string.h> // strcpy
|
||||||
#include <TeensyThreads.h>
|
#include <TeensyThreads.h>
|
||||||
@ -15,7 +14,7 @@ TeensyFileManager::TeensyFileManager()
|
|||||||
// FIXME: used to have 'enabled = sd.begin()' here, but we weren't
|
// 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
|
// using the enabled flag, so I've removed it to save the RAM for
|
||||||
// now; but eventually we need better error handling here
|
// now; but eventually we need better error handling here
|
||||||
sd.begin();
|
SD.begin(BUILTIN_SDCARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
TeensyFileManager::~TeensyFileManager()
|
TeensyFileManager::~TeensyFileManager()
|
||||||
@ -94,7 +93,7 @@ int8_t TeensyFileManager::readDir(const char *where, const char *suffix, char *o
|
|||||||
}
|
}
|
||||||
|
|
||||||
int8_t idxCount = 1;
|
int8_t idxCount = 1;
|
||||||
File f = sd.open(where);
|
File f = SD.open(where, FILE_READ);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
File e = f.openNextFile();
|
File e = f.openNextFile();
|
||||||
@ -105,7 +104,8 @@ int8_t TeensyFileManager::readDir(const char *where, const char *suffix, char *o
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip MAC fork files
|
// 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] == '.') {
|
if (outputFN[0] == '.') {
|
||||||
e.close();
|
e.close();
|
||||||
continue;
|
continue;
|
||||||
@ -166,8 +166,8 @@ bool TeensyFileManager::_prepCache(int8_t fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open the new one
|
// Open the new one
|
||||||
cacheFile = sd.open(cachedNames[fd], O_RDWR | O_CREAT);
|
cacheFile = SD.open(cachedNames[fd], FILE_WRITE);
|
||||||
if (!cacheFile.isOpen()) {
|
if (!cacheFile) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cacheFd = fd; // cache is live
|
cacheFd = fd; // cache is live
|
||||||
@ -198,12 +198,12 @@ bool TeensyFileManager::setSeekPosition(int8_t fd, uint32_t pos)
|
|||||||
// FIXME: this should be private
|
// FIXME: this should be private
|
||||||
void TeensyFileManager::seekToEnd(int8_t fd)
|
void TeensyFileManager::seekToEnd(int8_t fd)
|
||||||
{
|
{
|
||||||
FatFile f = sd.open(cachedNames[fd], FILE_READ);
|
File f = SD.open(cachedNames[fd], FILE_READ);
|
||||||
if (!f.isOpen()) {
|
if (!f) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileSeekPositions[fd] = f.fileSize();
|
fileSeekPositions[fd] = f.size();
|
||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,11 +223,11 @@ int TeensyFileManager::write(int8_t fd, const void *buf, int nbyte)
|
|||||||
|
|
||||||
uint32_t pos = fileSeekPositions[fd];
|
uint32_t pos = fileSeekPositions[fd];
|
||||||
|
|
||||||
if (!cacheFile.seekSet(pos)) {
|
if (!cacheFile.seek(pos)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cacheFile.write(buf, nbyte) != nbyte) {
|
if (cacheFile.write((const uint8_t *)buf, (size_t)nbyte) != (size_t)nbyte) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +251,7 @@ int TeensyFileManager::read(int8_t fd, void *buf, int nbyte)
|
|||||||
_prepCache(fd);
|
_prepCache(fd);
|
||||||
|
|
||||||
uint32_t pos = fileSeekPositions[fd];
|
uint32_t pos = fileSeekPositions[fd];
|
||||||
if (!cacheFile.seekSet(pos)) {
|
if (!cacheFile.seek(pos)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fileSeekPositions[fd] += nbyte;
|
fileSeekPositions[fd] += nbyte;
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
#include "filemanager.h"
|
#include "filemanager.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <SdFat.h>
|
#include <SD.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
class TeensyFileManager : public FileManager {
|
class TeensyFileManager : public FileManager {
|
||||||
public:
|
public:
|
||||||
@ -30,11 +31,10 @@ class TeensyFileManager : public FileManager {
|
|||||||
bool _prepCache(int8_t fd);
|
bool _prepCache(int8_t fd);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
volatile int8_t numCached;
|
int8_t numCached;
|
||||||
|
|
||||||
volatile SdFatSdio sd;
|
int8_t cacheFd;
|
||||||
volatile int8_t cacheFd;
|
File cacheFile;
|
||||||
volatile FatFile cacheFile;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,7 +23,8 @@ void TeensySpeaker::toggle(uint32_t c)
|
|||||||
mixerValue >>= (16-g_volume);
|
mixerValue >>= (16-g_volume);
|
||||||
|
|
||||||
// FIXME: glad it's DAC0 and all, but... how does that relate to the pin passed in the constructor?
|
// 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)
|
void TeensySpeaker::maintainSpeaker(uint32_t c, uint64_t runtimeInMicros)
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#define RESETPIN 39
|
#define RESETPIN 39
|
||||||
#define BATTERYPIN 32
|
#define BATTERYPIN 32
|
||||||
#define SPEAKERPIN A21
|
#define SPEAKERPIN 19 // FIXME this isn't right
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "teensy-crash.h"
|
#include "teensy-crash.h"
|
||||||
@ -35,13 +35,6 @@ BIOS bios;
|
|||||||
|
|
||||||
static time_t getTeensy3Time() { return Teensy3Clock.get(); }
|
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()
|
void setup()
|
||||||
{
|
{
|
||||||
Serial.begin(230400);
|
Serial.begin(230400);
|
||||||
@ -65,6 +58,8 @@ void setup()
|
|||||||
pinMode(RESETPIN, INPUT);
|
pinMode(RESETPIN, INPUT);
|
||||||
digitalWrite(RESETPIN, HIGH);
|
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 :/
|
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
|
analogReadRes(8); // We only need 8 bits of resolution (0-255) for battery & paddles
|
||||||
analogReadAveraging(4); // ?? dunno if we need this or not.
|
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(SPEAKERPIN, OUTPUT); // analog speaker output, used as digital volume control
|
||||||
pinMode(BATTERYPIN, INPUT);
|
pinMode(BATTERYPIN, INPUT);
|
||||||
|
*/
|
||||||
|
|
||||||
println("creating virtual hardware");
|
println("creating virtual hardware");
|
||||||
g_speaker = new TeensySpeaker(SPEAKERPIN);
|
g_speaker = new TeensySpeaker(SPEAKERPIN);
|
||||||
@ -111,7 +107,7 @@ void setup()
|
|||||||
g_keyboard = new TeensyKeyboard(g_vm->getKeyboard());
|
g_keyboard = new TeensyKeyboard(g_vm->getKeyboard());
|
||||||
|
|
||||||
println(" paddles");
|
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
|
// Now that all the virtual hardware is glued together, reset the VM
|
||||||
println("Resetting 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.
|
// 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...
|
// The alternative is to build a more stable buck/boost regulator for reference...
|
||||||
|
|
||||||
|
println("FIXME: analogReference for Teensy 4.0 => batteryLevel");
|
||||||
|
/*
|
||||||
analogReference(INTERNAL);
|
analogReference(INTERNAL);
|
||||||
batteryLevel = analogRead(BATTERYPIN);
|
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.
|
/* 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
|
* With a resistor voltage divider of Z1=39k, Z2=10k we're looking at roughly 20.4% of
|
||||||
|
Loading…
Reference in New Issue
Block a user