/
main.cpp
185 lines (161 loc) · 6.02 KB
/
main.cpp
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
#include "mbed.h"
#include "EasyAttach_CameraAndLCD.h"
/**** User Selection *********/
/** JPEG out setting **/
#define JPEG_SEND (1) /* Select 0(JPEG images are not output to PC) or 1(JPEG images are output to PC on USB(CDC) for focusing the camera) */
#define JPEG_ENCODE_QUALITY (75) /* JPEG encode quality (min:1, max:75 (Considering the size of JpegBuffer, about 75 is the upper limit.)) */
#define VFIELD_INT_SKIP_CNT (0) /* A guide for GR-LYCHEE. 0:60fps, 1:30fps, 2:20fps, 3:15fps, 4:12fps, 5:10fps */
/*****************************/
/* Video input and LCD layer 0 output */
#define VIDEO_FORMAT (DisplayBase::VIDEO_FORMAT_YCBCR422)
#define GRAPHICS_FORMAT (DisplayBase::GRAPHICS_FORMAT_YCBCR422)
#define WR_RD_WRSWA (DisplayBase::WR_RD_WRSWA_32_16BIT)
#define DATA_SIZE_PER_PIC (2u)
/*! Frame buffer stride: Frame buffer stride should be set to a multiple of 32 or 128
in accordance with the frame buffer burst transfer mode. */
#if MBED_CONF_APP_LCD
#define VIDEO_PIXEL_HW LCD_PIXEL_WIDTH
#define VIDEO_PIXEL_VW LCD_PIXEL_HEIGHT
#if ((VIDEO_PIXEL_HW * 2 / VIDEO_PIXEL_VW) >= 3)
#define ASPECT_RATIO_16_9 (1)
#endif
#else
#define VIDEO_PIXEL_HW (640u) /* VGA */
#define VIDEO_PIXEL_VW (480u) /* VGA */
#endif
#define FRAME_BUFFER_STRIDE (((VIDEO_PIXEL_HW * DATA_SIZE_PER_PIC) + 31u) & ~31u)
#define FRAME_BUFFER_HEIGHT (VIDEO_PIXEL_VW)
DisplayBase Display;
#if defined(__ICCARM__)
#pragma data_alignment=32
static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]@ ".mirrorram";
#else
static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]__attribute((section("NC_BSS"),aligned(32)));
#endif
#if JPEG_SEND
#include "JPEG_Converter.h"
#include "DisplayApp.h"
#include "dcache-control.h"
#if defined(__ICCARM__)
#pragma data_alignment=32
static uint8_t JpegBuffer[2][1024 * 64];
#else
static uint8_t JpegBuffer[2][1024 * 64]__attribute((aligned(32)));
#endif
static size_t jcu_encode_size[2];
static JPEG_Converter Jcu;
static int jcu_buf_index_write = 0;
static int jcu_buf_index_write_done = 0;
static int jcu_buf_index_read = 0;
static volatile int jcu_encoding = 0;
static volatile int image_change = 0;
static DisplayApp display_app;
static int Vfield_Int_Cnt = 0;
static void JcuEncodeCallBackFunc(JPEG_Converter::jpeg_conv_error_t err_code) {
if (err_code == JPEG_Converter::JPEG_CONV_OK) {
jcu_buf_index_write_done = jcu_buf_index_write;
image_change = 1;
}
jcu_encoding = 0;
}
static void snapshot(void) {
while ((jcu_encoding == 1) || (image_change == 0)) {
ThisThread::sleep_for(1);
}
jcu_buf_index_read = jcu_buf_index_write_done;
image_change = 0;
display_app.SendJpeg(JpegBuffer[jcu_buf_index_read], (int)jcu_encode_size[jcu_buf_index_read]);
}
static void IntCallbackFunc_Vfield(DisplayBase::int_type_t int_type) {
if (Vfield_Int_Cnt < VFIELD_INT_SKIP_CNT) {
Vfield_Int_Cnt++;
return;
}
Vfield_Int_Cnt = 0;
//Interrupt callback function
if (jcu_encoding == 0) {
JPEG_Converter::bitmap_buff_info_t bitmap_buff_info;
JPEG_Converter::encode_options_t encode_options;
bitmap_buff_info.width = VIDEO_PIXEL_HW;
bitmap_buff_info.height = VIDEO_PIXEL_VW;
bitmap_buff_info.format = JPEG_Converter::WR_RD_YCbCr422;
bitmap_buff_info.buffer_address = (void *)user_frame_buffer0;
encode_options.encode_buff_size = sizeof(JpegBuffer[0]);
encode_options.p_EncodeCallBackFunc = &JcuEncodeCallBackFunc;
encode_options.input_swapsetting = JPEG_Converter::WR_RD_WRSWA_32_16_8BIT;
jcu_encoding = 1;
if (jcu_buf_index_read == jcu_buf_index_write) {
jcu_buf_index_write ^= 1; // toggle
}
jcu_encode_size[jcu_buf_index_write] = 0;
dcache_invalid(JpegBuffer[jcu_buf_index_write], sizeof(JpegBuffer[0]));
if (Jcu.encode(&bitmap_buff_info, JpegBuffer[jcu_buf_index_write],
&jcu_encode_size[jcu_buf_index_write], &encode_options) != JPEG_Converter::JPEG_CONV_OK) {
jcu_encode_size[jcu_buf_index_write] = 0;
jcu_encoding = 0;
}
}
}
#endif
static void Start_Video_Camera(void) {
// Video capture setting (progressive form fixed)
Display.Video_Write_Setting(
DisplayBase::VIDEO_INPUT_CHANNEL_0,
DisplayBase::COL_SYS_NTSC_358,
(void *)user_frame_buffer0,
FRAME_BUFFER_STRIDE,
VIDEO_FORMAT,
WR_RD_WRSWA,
VIDEO_PIXEL_VW,
VIDEO_PIXEL_HW
);
EasyAttach_CameraStart(Display, DisplayBase::VIDEO_INPUT_CHANNEL_0);
}
#if MBED_CONF_APP_LCD
static void Start_LCD_Display(void) {
DisplayBase::rect_t rect;
rect.vs = 0;
rect.vw = LCD_PIXEL_HEIGHT;
rect.hs = 0;
rect.hw = LCD_PIXEL_WIDTH;
Display.Graphics_Read_Setting(
DisplayBase::GRAPHICS_LAYER_0,
(void *)user_frame_buffer0,
FRAME_BUFFER_STRIDE,
GRAPHICS_FORMAT,
WR_RD_WRSWA,
&rect
);
Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_0);
ThisThread::sleep_for(50);
EasyAttach_LcdBacklight(true);
}
#endif
int main(void) {
// Initialize the background to black
for (uint32_t i = 0; i < sizeof(user_frame_buffer0); i += 2) {
user_frame_buffer0[i + 0] = 0x10;
user_frame_buffer0[i + 1] = 0x80;
}
#if ASPECT_RATIO_16_9
EasyAttach_Init(Display, 640, 360); //aspect ratio 16:9
#else
EasyAttach_Init(Display); //aspect ratio 4:3
#endif
#if JPEG_SEND
Jcu.SetQuality(JPEG_ENCODE_QUALITY);
// Interrupt callback function setting (Field end signal for recording function in scaler 0)
Display.Graphics_Irq_Handler_Set(DisplayBase::INT_TYPE_S0_VFIELD, 0, IntCallbackFunc_Vfield);
#endif
Start_Video_Camera();
#if MBED_CONF_APP_LCD
Start_LCD_Display();
#endif
while (1) {
#if JPEG_SEND
snapshot();
#else
ThisThread::sleep_for(1000);
#endif
}
}