#include <stdint.h>
#include <RA8876_t41_p.h>
#include "Teensy_Camera.h"
#define USE_DB5_SHIELD
#define useRA9976
#define DVP_CAMERA_OV5640
#ifdef DVP_CAMERA_OV2640
#include "Teensy_OV2640/OV2640.h"
OV2640 omni;
Camera camera(omni);
#define CameraID OV2640a
#define MIRROR_FLIP_CAMERA
#else
//define DVP_CAMERA_OV5640
#include "Teensy_OV5640/OV5640.h"
OV5640 omni;
Camera camera(omni);
#define CameraID OV5640a
#define MIRROR_FLIP_CAMERA
#endif
//set cam configuration - need to remember when saving jpeg
framesize_t camera_framesize = FRAMESIZE_SVGA; // FRAMESIZE_1024X600;
pixformat_t camera_format = RGB565;
bool useGPIO = false;
//Set up Display
#ifdef ARDUINO_TEENSY_DEVBRD4
#undef USE_MMOD_ATP_ADAPTER
#define TFT_CS 10 // AD_B0_02
#define TFT_DC 25 // AD_B0_03
#define TFT_RST 24
#define VSYNC_PIN 21
#elif defined(ARDUINO_TEENSY_DEVBRD5)
#undef USE_MMOD_ATP_ADAPTER
#define DB5_USE_CSI
#define VSYNC_PIN 21
uint8_t dc = 55;
uint8_t cs = 53;
uint8_t rst = 54;
#endif
RA8876_t41_p tft = RA8876_t41_p(dc, cs, rst); //(dc, cs, rst)
#if defined(ARDUINO_TEENSY_DEVBRD4) || defined(ARDUINO_TEENSY_DEVBRD5)
extern "C" bool sdram_begin(uint8_t external_sdram_size, uint8_t clock, uint8_t useDQS);
#endif
#define TFT_BLACK BLACK
#define TFT_YELLOW YELLOW
#define TFT_RED RED
#define TFT_GREEN GREEN
#define TFT_BLUE BLUE
//#define CENTER RA8876_t3::CENTER
// Setup framebuffers
DMAMEM uint16_t FRAME_WIDTH, FRAME_HEIGHT;
uint16_t *frameBuffer = nullptr;
uint16_t *frameBuffer2 = nullptr;
void setup() {
Serial.begin(921600);
while (!Serial && millis() < 5000) {}
#if defined(USB_DUAL_SERIAL) || defined(USB_TRIPLE_SERIAL)
SerialUSB1.begin(921600);
#endif
if (CrashReport) {
Serial.print(CrashReport);
Serial.println("Press any key to continue");
}
tft.setBusWidth(16);
tft.setFlexIOPins(56, 52, 40);
tft.begin(12);
tft.fillScreen(TFT_BLACK);
delay(500);
tft.fillScreen(TFT_BLACK);
// try using the CSI pins on devboard 5
camera.setPins(65, 64, 17, 16, 57, 27, 26, 67, 66, 21, 20, 23, 22, 58);
// FRAMESIZE_VGA = 0,
// FRAMESIZE_QQVGA, // 160x120
// FRAMESIZE_QVGA, // 320x240
// FRAMESIZE_480X320,
// FRAMESIZE_320X320, // 320x320
// FRAMESIZE_QVGA4BIT,
// FRAMESIZE_QCIF,
// FRAMESIZE_CIF,
// FRAMESIZE_SVGA, //800, 600
// FRAMESIZE_UXGA, //1500, 1200
// FRAMESIZE_1024X600
uint8_t status = 0;
status = camera.begin(camera_framesize, camera_format, 30, CameraID, useGPIO);
Serial.printf("Begin status: %d\n", status);
if (!status) {
Serial.println("Camera failed to start again program halted");
while (1) {}
}
camera.debug(false);
frameBuffer = (uint16_t *)((((uint32_t)(sdram_malloc(camera.width() * camera.height() * 2 + 32)) + 32) & 0xffffffe0));
frameBuffer2 = (uint16_t *)((((uint32_t)(sdram_malloc(camera.width() * camera.height() * 2 + 32)) + 32) & 0xffffffe0));
Serial.printf("Camera Buffers: %p %p\n", frameBuffer, frameBuffer2);
//camera.setBrightness(0); // -2 to +2
//camera.setContrast(0); // -2 to +2
//camera.setSaturation(0); // -2 to +2
//omni.setSpecialEffect(RETRO); // NOEFFECT, NEGATIVE, BW, REDDISH, GREEISH, BLUEISH, RETRO
//omni.setWBmode(0); // AWB ON, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home
Serial.println("Camera settings:");
Serial.print("\twidth = ");
Serial.println(camera.width());
Serial.print("\theight = ");
Serial.println(camera.height());
//Serial.print("\tbits per pixel = NA");
//Serial.println(camera.bitsPerPixel());
Serial.println();
Serial.printf("TFT Width = %u Height = %u\n\n", tft.width(), tft.height());
FRAME_HEIGHT = camera.height();
FRAME_WIDTH = camera.width();
Serial.printf("ImageSize (w,h): %d, %d\n", FRAME_WIDTH, FRAME_HEIGHT);
/**********************************************************/
tft.graphicMode(true);
tft.setRotation(2);
tft.onDMACompleteCB(&dma_complete_cb);
wait_for_user_input();
}
int end_wait_char = 0;
void wait_for_user_input() {
while (Serial.read() != -1) {}
Serial.println("Press any key to continue");
while ((end_wait_char = Serial.read()) == -1) {}
while (Serial.read() != -1) {}
tft.fillScreen(BLUE);
}
uint8_t loop_count = 0;
volatile bool dma_active = false;
void dma_complete_cb() {
dma_active = false;
}
void loop() {
if (Serial.available()) {
wait_for_user_input();
}
loop_count++;
uint16_t *pframeBuffer = (loop_count & 1) ? frameBuffer : frameBuffer2;
//memset(pframeBuffer, 0, camera.width() * camera.height() * 2);
uint32_t start_time = micros();
camera.readFrame(pframeBuffer, camera.width() * camera.height());
uint32_t after_read_frame = micros();
int start_x = (tft.width() - camera.width()) / 2;
int start_y = (tft.height() - camera.height()) / 2;
if (end_wait_char == 'w') {
tft.useCanvas(false);
//Serial.printf("Call WriteRect(%d, %d, %d, %d, %p\n", start_x, start_y, camera.width(), camera.height(), pframeBuffer);
tft.writeRect(start_x, start_y, camera.width(), camera.height(), pframeBuffer);
//delay(500);
} else {
while (dma_active) {}
uint32_t after_dma_active = micros();
tft.updateScreen();
uint32_t after_updateScreen = micros();
dma_active = true;
tft.useCanvas(true);
tft.pushPixels16bitDMA(pframeBuffer, start_x, start_y, camera.width(), camera.height()); // FLASHMEM buffer
uint32_t after_push_pixels = micros();
Serial.printf("%u %u %u %u\n", after_read_frame - start_time, after_dma_active - after_read_frame,
after_updateScreen - after_dma_active, after_push_pixels - after_updateScreen);
//delay(750);
}
}