mirror of https://github.com/JorjBauer/aiie.git
convert to ili9341_t3n library to use full DMA transfers
This commit is contained in:
parent
70885ab240
commit
e138f7be3f
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#define _clock 75000000
|
#define _clock 75000000
|
||||||
|
|
||||||
|
|
||||||
#define PIN_RST 8
|
#define PIN_RST 8
|
||||||
#define PIN_DC 9
|
#define PIN_DC 9
|
||||||
#define PIN_CS 10
|
#define PIN_CS 10
|
||||||
|
@ -29,14 +30,15 @@
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "applevm.h"
|
#include "applevm.h"
|
||||||
|
|
||||||
volatile DMAMEM uint16_t dmaBuffer[240][320]; // 240 rows, 320 columns
|
DMAMEM uint16_t dmaBuffer[240][320]; // 240 rows, 320 columns
|
||||||
|
|
||||||
#define RGBto565(r,g,b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3))
|
#define RGBto565(r,g,b) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | ((b) >> 3))
|
||||||
#define _565toR(c) ( ((c) & 0xF800) >> 8 )
|
#define _565toR(c) ( ((c) & 0xF800) >> 8 )
|
||||||
#define _565toG(c) ( ((c) & 0x07E0) >> 5 )
|
#define _565toG(c) ( ((c) & 0x07E0) >> 5 )
|
||||||
#define _565toB(c) ( ((c) & 0x001F) )
|
#define _565toB(c) ( ((c) & 0x001F) )
|
||||||
|
|
||||||
ILI9341_t3 tft = ILI9341_t3(PIN_CS, PIN_DC, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO);
|
//ILI9341_t3 tft = ILI9341_t3(PIN_CS, PIN_DC, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO);
|
||||||
|
ILI9341_t3n tft = ILI9341_t3n(PIN_CS, PIN_DC, PIN_RST, PIN_MOSI, PIN_SCK, PIN_MISO);
|
||||||
|
|
||||||
DMAChannel dmatx;
|
DMAChannel dmatx;
|
||||||
DMASetting dmaSetting;
|
DMASetting dmaSetting;
|
||||||
|
@ -100,37 +102,10 @@ TeensyDisplay::TeensyDisplay()
|
||||||
{
|
{
|
||||||
memset(dmaBuffer, 0x80, sizeof(dmaBuffer));
|
memset(dmaBuffer, 0x80, sizeof(dmaBuffer));
|
||||||
|
|
||||||
tft.begin();
|
tft.begin(_clock);
|
||||||
tft.setRotation(3);
|
tft.setRotation(3);
|
||||||
tft.setClock(_clock);
|
tft.setFrameBuffer((uint16_t *)dmaBuffer);
|
||||||
|
tft.useFrameBuffer(true);
|
||||||
// Set up automatic DMA transfers. cf.
|
|
||||||
// https://forum.pjrc.com/threads/25778-Could-there-be-something-like-an-ISR-template-function/page4
|
|
||||||
#if 0
|
|
||||||
dmaSetting.TCD->CSR = 0;
|
|
||||||
dmaSetting.TCD->SADDR = dmaBuffer;
|
|
||||||
dmaSetting.TCD->SOFF = 2; // 2 bytes per pixel
|
|
||||||
dmaSetting.TCD->ATTR_SRC = 1;
|
|
||||||
dmaSetting.TCD->NBYTES = 2;
|
|
||||||
dmaSetting.TCD->SLAST = -320*240*2;
|
|
||||||
dmaSetting.TCD->BITER = 320*240;
|
|
||||||
dmaSetting.TCD->CITER = 320*240;
|
|
||||||
|
|
||||||
dmaSetting.TCD->DADDR = &LPSPI4_TDR; // FIXME is this correct?
|
|
||||||
dmaSetting.TCD->DOFF = 0;
|
|
||||||
dmaSetting.TCD->ATTR_DST = 1;
|
|
||||||
dmaSetting.TCD->DLASTSGA = 0;
|
|
||||||
|
|
||||||
// Make it loop on itself
|
|
||||||
dmaSetting.replaceSettingsOnCompletion(dmaSetting);
|
|
||||||
|
|
||||||
dmatx.begin(false);
|
|
||||||
dmatx.triggerAtHardwareEvent(DMAMUX_SOURCE_LPSPI4_TX); // FIXME what's the right source ID
|
|
||||||
dmatx = &dmaSetting;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// LCD initialization complete
|
|
||||||
|
|
||||||
tft.fillScreen(ILI9341_BLACK);
|
tft.fillScreen(ILI9341_BLACK);
|
||||||
|
|
||||||
driveIndicator[0] = driveIndicator[1] = false;
|
driveIndicator[0] = driveIndicator[1] = false;
|
||||||
|
@ -181,12 +156,9 @@ void TeensyDisplay::flush()
|
||||||
|
|
||||||
void TeensyDisplay::blit()
|
void TeensyDisplay::blit()
|
||||||
{
|
{
|
||||||
// The goal here is for blitting to happen automatically in DMA transfers.
|
// Start DMA transfers if they aren't running
|
||||||
|
if (!tft.asyncUpdateActive())
|
||||||
// Since that isn't the case yet, here's a manual blit of the whole
|
tft.updateScreenAsync(true);
|
||||||
// screen (b/c the rect is kinda meaningless in the final "draw
|
|
||||||
// everything always" DMA mode)
|
|
||||||
tft.writeRect(0,0,320,240,(const uint16_t *)dmaBuffer);
|
|
||||||
|
|
||||||
// draw overlay, if any, occasionally
|
// draw overlay, if any, occasionally
|
||||||
{
|
{
|
||||||
|
@ -202,15 +174,7 @@ void TeensyDisplay::blit()
|
||||||
|
|
||||||
void TeensyDisplay::blit(AiieRect r)
|
void TeensyDisplay::blit(AiieRect r)
|
||||||
{
|
{
|
||||||
// It's probably faster to just blit the whole thing, rather than a piece,
|
// Nothing to do here, since we're regularly blitting the whole screen via DMA
|
||||||
// because of how it streams data easily when the buffer aligns properly.
|
|
||||||
tft.writeRect(0,0,320,240,(const uint16_t *)dmaBuffer);
|
|
||||||
|
|
||||||
// ... but if we wanted to blit just part, we'd have to create a new
|
|
||||||
// subset of teh dmaBuffer that has the right row length to match
|
|
||||||
// the rect width we're blitting, and then do something like this:
|
|
||||||
//
|
|
||||||
// tft.writeRect(r.left+HOFFSET,,r.top+VOFFSET,r.right-r.left+HOFFSET,r.bottom-r.top+VOFFSET,(const uint16_t *)some_subset_of_dmaBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TeensyDisplay::drawCharacter(uint8_t mode, uint16_t x, uint8_t y, char c)
|
void TeensyDisplay::drawCharacter(uint8_t mode, uint16_t x, uint8_t y, char c)
|
||||||
|
@ -381,3 +345,8 @@ void TeensyDisplay::cachePixel(uint16_t x, uint16_t y, uint8_t color)
|
||||||
cacheDoubleWidePixel(x>>1, y, color);
|
cacheDoubleWidePixel(x>>1, y, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t TeensyDisplay::frameCount()
|
||||||
|
{
|
||||||
|
return tft.frameCount();
|
||||||
|
}
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
#define __TEENSY_DISPLAY_H
|
#define __TEENSY_DISPLAY_H
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ILI9341_t3.h>
|
#include <ILI9341_t3n.h>
|
||||||
|
|
||||||
#include "physicaldisplay.h"
|
#include "physicaldisplay.h"
|
||||||
|
|
||||||
class UTFT;
|
|
||||||
class BIOS;
|
class BIOS;
|
||||||
|
|
||||||
class TeensyDisplay : public PhysicalDisplay {
|
class TeensyDisplay : public PhysicalDisplay {
|
||||||
|
@ -32,6 +31,7 @@ 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);
|
||||||
|
|
||||||
|
uint32_t frameCount();
|
||||||
private:
|
private:
|
||||||
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);
|
||||||
|
|
|
@ -254,6 +254,7 @@ void runDisplay(uint32_t now)
|
||||||
static uint32_t microsAtStart = 0;
|
static uint32_t microsAtStart = 0;
|
||||||
static uint32_t microsForNext = micros();
|
static uint32_t microsForNext = micros();
|
||||||
static uint32_t lastFps = 0;
|
static uint32_t lastFps = 0;
|
||||||
|
static uint32_t displayFrameCount = 0;
|
||||||
|
|
||||||
THREADED {
|
THREADED {
|
||||||
// If it's time to draw the next frame, then do so
|
// If it's time to draw the next frame, then do so
|
||||||
|
@ -278,10 +279,21 @@ void runDisplay(uint32_t now)
|
||||||
|
|
||||||
// Once a second, start counting all over again
|
// Once a second, start counting all over again
|
||||||
if (now >= nextResetMicros) {
|
if (now >= nextResetMicros) {
|
||||||
lastFps = refreshCount;
|
uint32_t newFrameCount = ((TeensyDisplay *)g_display)->frameCount();
|
||||||
|
|
||||||
|
// There are two "FPS" counters here, actually. One is how often
|
||||||
|
// we're polling the Apple //e memory to refresh the DMA buffer,
|
||||||
|
// and to show that, we'd use this:
|
||||||
|
// lastFps = refreshCount;
|
||||||
|
// The other is how often the DMA code is refreshing the actual
|
||||||
|
// display, and to show that, we'd use this:
|
||||||
|
lastFps = newFrameCount - displayFrameCount;
|
||||||
#ifdef DEBUG_TIMING
|
#ifdef DEBUG_TIMING
|
||||||
println("Display running at ", lastFps, " FPS");
|
// ... and this debugging code shows both.
|
||||||
|
println("DMA buffer refresh at ", refreshCount, " FPS");
|
||||||
|
println("Display refresh at ", newFrameCount - displayFrameCount, " FPS");
|
||||||
#endif
|
#endif
|
||||||
|
displayFrameCount = newFrameCount;
|
||||||
nextResetMicros = now + 1000000;
|
nextResetMicros = now + 1000000;
|
||||||
refreshCount = 0;
|
refreshCount = 0;
|
||||||
microsAtStart = now;
|
microsAtStart = now;
|
||||||
|
|
Loading…
Reference in New Issue