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 PIN_RST 8
|
||||
#define PIN_DC 9
|
||||
#define PIN_CS 10
|
||||
|
@ -29,14 +30,15 @@
|
|||
#include "globals.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 _565toR(c) ( ((c) & 0xF800) >> 8 )
|
||||
#define _565toG(c) ( ((c) & 0x07E0) >> 5 )
|
||||
#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;
|
||||
DMASetting dmaSetting;
|
||||
|
@ -100,37 +102,10 @@ TeensyDisplay::TeensyDisplay()
|
|||
{
|
||||
memset(dmaBuffer, 0x80, sizeof(dmaBuffer));
|
||||
|
||||
tft.begin();
|
||||
tft.begin(_clock);
|
||||
tft.setRotation(3);
|
||||
tft.setClock(_clock);
|
||||
|
||||
// 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.setFrameBuffer((uint16_t *)dmaBuffer);
|
||||
tft.useFrameBuffer(true);
|
||||
tft.fillScreen(ILI9341_BLACK);
|
||||
|
||||
driveIndicator[0] = driveIndicator[1] = false;
|
||||
|
@ -181,12 +156,9 @@ void TeensyDisplay::flush()
|
|||
|
||||
void TeensyDisplay::blit()
|
||||
{
|
||||
// The goal here is for blitting to happen automatically in DMA transfers.
|
||||
|
||||
// Since that isn't the case yet, here's a manual blit of the whole
|
||||
// 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);
|
||||
// Start DMA transfers if they aren't running
|
||||
if (!tft.asyncUpdateActive())
|
||||
tft.updateScreenAsync(true);
|
||||
|
||||
// draw overlay, if any, occasionally
|
||||
{
|
||||
|
@ -202,15 +174,7 @@ void TeensyDisplay::blit()
|
|||
|
||||
void TeensyDisplay::blit(AiieRect r)
|
||||
{
|
||||
// It's probably faster to just blit the whole thing, rather than a piece,
|
||||
// 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);
|
||||
// Nothing to do here, since we're regularly blitting the whole screen via DMA
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TeensyDisplay::frameCount()
|
||||
{
|
||||
return tft.frameCount();
|
||||
}
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
#define __TEENSY_DISPLAY_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <ILI9341_t3.h>
|
||||
#include <ILI9341_t3n.h>
|
||||
|
||||
#include "physicaldisplay.h"
|
||||
|
||||
class UTFT;
|
||||
class BIOS;
|
||||
|
||||
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 cachePixel(uint16_t x, uint16_t y, uint8_t color);
|
||||
|
||||
uint32_t frameCount();
|
||||
private:
|
||||
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);
|
||||
|
|
|
@ -254,6 +254,7 @@ void runDisplay(uint32_t now)
|
|||
static uint32_t microsAtStart = 0;
|
||||
static uint32_t microsForNext = micros();
|
||||
static uint32_t lastFps = 0;
|
||||
static uint32_t displayFrameCount = 0;
|
||||
|
||||
THREADED {
|
||||
// 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
|
||||
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
|
||||
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
|
||||
displayFrameCount = newFrameCount;
|
||||
nextResetMicros = now + 1000000;
|
||||
refreshCount = 0;
|
||||
microsAtStart = now;
|
||||
|
|
Loading…
Reference in New Issue