-
Notifications
You must be signed in to change notification settings - Fork 0
/
CamToIli9341.ino
189 lines (161 loc) · 6.4 KB
/
CamToIli9341.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include <TJpg_Decoder.h>
#include <TFT_eSPI.h>
//################################################## ###########################
//
// WARNING!!! Make sure that you have either selected ESP32 Wrover Module,
// or another board which has PSRAM enabled
//
//
#include "esp_camera.h"
// Select camera model
//#define CAMERA_MODEL_WROVER_KIT
//#define CAMERA_MODEL_ESP_EYE
//#define CAMERA_MODEL_M5STACK_PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE
#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"
void setupLedFlash(int pin);
// #if defined(LED_GPIO_NUM)
// setupLedFlash(LED_GPIO_NUM);
//#endif
//################################################## ###########################
#define USE_DMA
// Include the jpeg decoder library
#include <TJpg_Decoder.h>
#ifdef USE_DMA
uint16_t dmaBuffer1[16 * 16]; // Toggle buffer for 16*16 MCU block, 512bytes
uint16_t dmaBuffer2[16 * 16]; // Toggle buffer for 16*16 MCU block, 512bytes
uint16_t* dmaBufferPtr = dmaBuffer1;
bool dmaBufferSel = 0;
#endif
// Include the TFT library https://github.com/Bodmer/TFT_eSPI
#include "SPI.h"
#include <TFT_eSPI.h> // Hardware-specific library
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
// This next function will be called during decoding of the jpeg file to render each
// 16x16 or 8x8 image tile (Minimum Coding Unit) to the TFT.
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap) {
// Stop further decoding as image is running off bottom of screen
if (y >= tft.height()) return 0;
// STM32F767 processor takes 43ms just to decode (and not draw) jpeg (-Os compile option)
// Total time to decode and also draw to TFT:
// SPI 54MHz=71ms, with DMA 50ms, 71-43 = 28ms spent drawing, so DMA is complete before next MCU block is ready
// Apparent performance benefit of DMA = 71/50 = 42%, 50 - 43 = 7ms lost elsewhere
// SPI 27MHz=95ms, with DMA 52ms. 95-43 = 52ms spent drawing, so DMA is *just* complete before next MCU block is ready!
// Apparent performance benefit of DMA = 95/52 = 83%, 52 - 43 = 9ms lost elsewhere
#ifdef USE_DMA
// Double buffering is used, the bitmap is copied to the buffer by pushImageDMA() the
// bitmap can then be updated by the jpeg decoder while DMA is in progress
if (dmaBufferSel) dmaBufferPtr = dmaBuffer2;
else dmaBufferPtr = dmaBuffer1;
dmaBufferSel = !dmaBufferSel; // Toggle buffer selection
// pushImageDMA() will clip the image block at screen boundaries before initiating DMA
tft.pushImageDMA(x, y, w, h, bitmap, dmaBufferPtr); // Initiate DMA - blocking only if last DMA is not complete
// The DMA transfer of image block to the TFT is now in progress...
#else
// Non-DMA blocking alternative
tft.pushImage(x, y, w, h, bitmap); // Blocking, so only returns when image block is drawn
#endif
// Return 1 to decode next block.
return 1;
}
//################################################## ###########################
//
//##################### #################################################### ####
// #define LEDFlash 4
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println();
// digitalWrite(LEDFlash, LOW);
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 10000000;
config.pixel_format = PIXFORMAT_JPEG;
// config.LEDFlash = LED_GPIO_NUM;
//init with high specs to pre-allocate larger buffers
// config.LEDFlash = 0;l
if (psramFound()) {
config.frame_size = FRAMESIZE_QVGA; //FRAMESIZE_QVGA 320x240
config.jpeg_quality = 10; //< Quality of JPEG output. 0-63 lower means higher quality
config.fb_count = 2; //Number of frame buffers to be allocated. If more than one, then each frame will be acquired (double speed)
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
sensor_t* s = esp_camera_sensor_get();
s->set_contrast(s, 2); // -2 to 2
s->set_saturation(s, -2); // -2 to 2
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// Initialise the TFT
tft.begin();
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
tft.setRotation(3); //1:landscape 3:inv.landscape
#ifdef USE_DMA
tft.initDMA(); // To use SPI DMA you must call initDMA() to setup the DMA engine
#endif
// The jpeg image can be scaled down by a factor of 1, 2, 4, or 8
TJpgDec.setJpgScale(1);
// The color byte order can be swapped by the decoder
// using TJpgDec.setSwapBytes(true); or by the TFT_eSPI library:
tft.setSwapBytes(true);
// The decoder must be given the exact name of the rendering function above
TJpgDec.setCallback(tft_output);
}
//################################################## ###########################
//
//##################### #################################################### ####
void loop() {
camera_fb_t* fb = NULL;
esp_err_t res = ESP_OK;
//uint32_t last = millis();
fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Camera capture failed");
esp_camera_fb_return(fb);
return;
}
size_t fb_len = 0;
if (fb->format != PIXFORMAT_JPEG) {
Serial.println("Non-JPEG data not implemented");
return;
}
#ifdef USE_DMA
// Must use startWrite first so TFT chip select stays low during DMA and SPI channel settings remain configured
tft.startWrite();
#endif _
// Draw the image, top left at 0,0 - DMA request is handled in the call-back tft_output() in this sketch
//TJpgDec.drawJpg(0, 0, panda, sizeof(panda));
TJpgDec.drawJpg(0, 0, fb->buf, fb->len);
#ifdef USE_DMA
// Must use endWrite to release the TFT chip select and release the SPI channel
tft.endWrite();
#endif _
esp_camera_fb_return(fb);
}