Image rotation Sample. This program uses GraphicsFramework library and L3GD20 sensor.
Dependencies: GR-PEACH_video GraphicsFramework L3GD20 R_BSP mbed-rtos mbed
Fork of RGA_HelloWorld by
About L3GD20
L3GD20 is a 3-axis gyroscope sensor and can be controlled by using theI2C.
- Datasheet of L3GD20
http://www.st.com/content/ccc/resource/technical/document/datasheet/43/37/e3/06/b0/bf/48/bd/DM00036465.pdf/files/DM00036465.pdf/jcr:content/translations/en.DM00036465.pdf
About wiring
Sensor | GR-PEACH |
VDD | 3.3V |
SCL | D15 |
SDA | D14 |
SA0 | 3.3V |
CS | 3.3V |
GND | GND |
main.cpp@4:138b18a6ac7b, 2016-05-23 (annotated)
- Committer:
- 1050186
- Date:
- Mon May 23 10:03:17 2016 +0000
- Revision:
- 4:138b18a6ac7b
- Parent:
- 2:c7faef0ef374
First commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
1050186 | 0:84e4649e7707 | 1 | #include "mbed.h" |
1050186 | 4:138b18a6ac7b | 2 | #include "math.h" |
1050186 | 0:84e4649e7707 | 3 | #include "rga_func.h" |
1050186 | 0:84e4649e7707 | 4 | #include "DisplayBace.h" |
1050186 | 0:84e4649e7707 | 5 | #include "rtos.h" |
1050186 | 4:138b18a6ac7b | 6 | #include "L3GD20.h" |
1050186 | 0:84e4649e7707 | 7 | |
1050186 | 4:138b18a6ac7b | 8 | /**** LCD Parameter **********/ |
1050186 | 4:138b18a6ac7b | 9 | #define LCD_DE_MODE (0) |
1050186 | 4:138b18a6ac7b | 10 | #define LCD_SYNC_MODE (1) |
1050186 | 4:138b18a6ac7b | 11 | |
1050186 | 4:138b18a6ac7b | 12 | #define LCD_DOT_CLOCK (13.40f) // 13.4MHz |
1050186 | 0:84e4649e7707 | 13 | |
1050186 | 4:138b18a6ac7b | 14 | #define LCD_H_WIDTH (480u) |
1050186 | 4:138b18a6ac7b | 15 | #define LCD_H_BACK_PORCH (43u) |
1050186 | 4:138b18a6ac7b | 16 | #define LCD_H_FRONT_PORCH (52u) |
1050186 | 4:138b18a6ac7b | 17 | #define LCD_H_SYNC_WIDTH (41u) |
1050186 | 4:138b18a6ac7b | 18 | |
1050186 | 4:138b18a6ac7b | 19 | #define LCD_V_WIDTH (272u) |
1050186 | 4:138b18a6ac7b | 20 | #define LCD_V_BACK_PORCH (12u) |
1050186 | 4:138b18a6ac7b | 21 | #define LCD_V_FRONT_PORCH (2u) |
1050186 | 4:138b18a6ac7b | 22 | #define LCD_V_SYNC_WIDTH (10u) |
1050186 | 4:138b18a6ac7b | 23 | |
1050186 | 4:138b18a6ac7b | 24 | #define LCD_MODE (LCD_SYNC_MODE) |
1050186 | 4:138b18a6ac7b | 25 | |
1050186 | 4:138b18a6ac7b | 26 | /*****************************/ |
1050186 | 0:84e4649e7707 | 27 | |
1050186 | 0:84e4649e7707 | 28 | /* FRAME BUFFER Parameter */ |
dkato | 2:c7faef0ef374 | 29 | #define FRAME_BUFFER_BYTE_PER_PIXEL (2) |
1050186 | 4:138b18a6ac7b | 30 | #define FRAME_BUFFER_STRIDE (((LCD_H_WIDTH * FRAME_BUFFER_BYTE_PER_PIXEL) + 31u) & ~31u) |
1050186 | 0:84e4649e7707 | 31 | |
1050186 | 0:84e4649e7707 | 32 | DigitalOut lcd_pwon(P7_15); |
1050186 | 0:84e4649e7707 | 33 | DigitalOut lcd_blon(P8_1); |
1050186 | 0:84e4649e7707 | 34 | PwmOut lcd_cntrst(P8_15); |
1050186 | 0:84e4649e7707 | 35 | DisplayBase Display; |
1050186 | 4:138b18a6ac7b | 36 | L3GD20 gyro(I2C_SDA, I2C_SCL); |
1050186 | 0:84e4649e7707 | 37 | |
1050186 | 4:138b18a6ac7b | 38 | static uint8_t user_frame_buffer[FRAME_BUFFER_STRIDE * LCD_V_WIDTH]__attribute((aligned(32))); /* 32 bytes aligned */ |
1050186 | 4:138b18a6ac7b | 39 | static uint8_t user_frame_buffer2[FRAME_BUFFER_STRIDE * LCD_V_WIDTH]__attribute((aligned(32))); /* 32 bytes aligned */ |
1050186 | 0:84e4649e7707 | 40 | static frame_buffer_t frame_buffer_info; |
1050186 | 0:84e4649e7707 | 41 | static volatile int32_t vsync_count = 0; |
1050186 | 0:84e4649e7707 | 42 | |
1050186 | 0:84e4649e7707 | 43 | static void IntCallbackFunc_Vsync(DisplayBase::int_type_t int_type) { |
1050186 | 0:84e4649e7707 | 44 | /* Interrupt callback function for Vsync interruption */ |
1050186 | 0:84e4649e7707 | 45 | if (vsync_count > 0) { |
1050186 | 0:84e4649e7707 | 46 | vsync_count--; |
1050186 | 0:84e4649e7707 | 47 | } |
1050186 | 0:84e4649e7707 | 48 | } |
1050186 | 0:84e4649e7707 | 49 | |
1050186 | 0:84e4649e7707 | 50 | static void Wait_Vsync(const int32_t wait_count) { |
1050186 | 0:84e4649e7707 | 51 | /* Wait for the specified number of times Vsync occurs */ |
1050186 | 0:84e4649e7707 | 52 | vsync_count = wait_count; |
1050186 | 0:84e4649e7707 | 53 | while (vsync_count > 0) { |
1050186 | 0:84e4649e7707 | 54 | /* Do nothing */ |
1050186 | 0:84e4649e7707 | 55 | } |
1050186 | 0:84e4649e7707 | 56 | } |
1050186 | 0:84e4649e7707 | 57 | |
1050186 | 4:138b18a6ac7b | 58 | static void Swap_FrameBuffer(frame_buffer_t * frmbuf_info) { |
1050186 | 4:138b18a6ac7b | 59 | if (frmbuf_info->draw_buffer_index == 1) { |
1050186 | 4:138b18a6ac7b | 60 | frmbuf_info->draw_buffer_index = 0; |
1050186 | 4:138b18a6ac7b | 61 | } else { |
1050186 | 4:138b18a6ac7b | 62 | frmbuf_info->draw_buffer_index = 1; |
1050186 | 4:138b18a6ac7b | 63 | } |
1050186 | 4:138b18a6ac7b | 64 | } |
1050186 | 4:138b18a6ac7b | 65 | |
1050186 | 4:138b18a6ac7b | 66 | static void Update_LCD_Display(frame_buffer_t * frmbuf_info) { |
1050186 | 4:138b18a6ac7b | 67 | Display.Graphics_Read_Change(DisplayBase::GRAPHICS_LAYER_0, |
1050186 | 4:138b18a6ac7b | 68 | (void *)frmbuf_info->buffer_address[frmbuf_info->draw_buffer_index]); |
1050186 | 4:138b18a6ac7b | 69 | Wait_Vsync(1); |
1050186 | 4:138b18a6ac7b | 70 | } |
1050186 | 4:138b18a6ac7b | 71 | |
1050186 | 4:138b18a6ac7b | 72 | int main(void) { |
1050186 | 0:84e4649e7707 | 73 | /* Create DisplayBase object */ |
1050186 | 0:84e4649e7707 | 74 | DisplayBase::graphics_error_t error; |
1050186 | 4:138b18a6ac7b | 75 | float gx; |
1050186 | 4:138b18a6ac7b | 76 | float gy; |
1050186 | 4:138b18a6ac7b | 77 | float gz; |
1050186 | 4:138b18a6ac7b | 78 | |
1050186 | 4:138b18a6ac7b | 79 | memset(user_frame_buffer, 0, sizeof(user_frame_buffer)); |
1050186 | 4:138b18a6ac7b | 80 | memset(user_frame_buffer2, 0, sizeof(user_frame_buffer2)); |
1050186 | 4:138b18a6ac7b | 81 | frame_buffer_info.buffer_address[0] = user_frame_buffer; |
1050186 | 4:138b18a6ac7b | 82 | frame_buffer_info.buffer_address[1] = user_frame_buffer2; |
1050186 | 4:138b18a6ac7b | 83 | frame_buffer_info.buffer_count = 2; |
1050186 | 4:138b18a6ac7b | 84 | frame_buffer_info.show_buffer_index = 0; |
1050186 | 4:138b18a6ac7b | 85 | frame_buffer_info.draw_buffer_index = 0; |
1050186 | 4:138b18a6ac7b | 86 | frame_buffer_info.width = LCD_H_WIDTH; |
1050186 | 4:138b18a6ac7b | 87 | frame_buffer_info.byte_per_pixel = FRAME_BUFFER_BYTE_PER_PIXEL; |
1050186 | 4:138b18a6ac7b | 88 | frame_buffer_info.stride = LCD_H_WIDTH * FRAME_BUFFER_BYTE_PER_PIXEL; |
1050186 | 4:138b18a6ac7b | 89 | frame_buffer_info.height = LCD_V_WIDTH; |
1050186 | 4:138b18a6ac7b | 90 | frame_buffer_info.pixel_format = PIXEL_FORMAT_RGB565; |
1050186 | 4:138b18a6ac7b | 91 | |
1050186 | 4:138b18a6ac7b | 92 | lcd_pwon = 0; |
1050186 | 4:138b18a6ac7b | 93 | lcd_blon = 0; |
1050186 | 4:138b18a6ac7b | 94 | Thread::wait(100); |
1050186 | 4:138b18a6ac7b | 95 | |
1050186 | 4:138b18a6ac7b | 96 | lcd_pwon = 1; |
1050186 | 4:138b18a6ac7b | 97 | lcd_blon = 1; |
1050186 | 4:138b18a6ac7b | 98 | Thread::wait(100); |
1050186 | 4:138b18a6ac7b | 99 | |
1050186 | 0:84e4649e7707 | 100 | DisplayBase::lcd_config_t lcd_config; |
1050186 | 0:84e4649e7707 | 101 | PinName lvds_pin[8] = { |
1050186 | 0:84e4649e7707 | 102 | /* data pin */ |
1050186 | 0:84e4649e7707 | 103 | P5_7, P5_6, P5_5, P5_4, P5_3, P5_2, P5_1, P5_0 |
1050186 | 0:84e4649e7707 | 104 | }; |
1050186 | 4:138b18a6ac7b | 105 | DisplayBase::rect_t rect; |
1050186 | 0:84e4649e7707 | 106 | |
1050186 | 0:84e4649e7707 | 107 | lcd_config.lcd_type = DisplayBase::LCD_TYPE_LVDS; |
1050186 | 4:138b18a6ac7b | 108 | lcd_config.intputClock = 66.67f; |
1050186 | 4:138b18a6ac7b | 109 | lcd_config.outputClock = LCD_DOT_CLOCK; |
1050186 | 0:84e4649e7707 | 110 | lcd_config.lcd_outformat = DisplayBase::LCD_OUTFORMAT_RGB888; |
1050186 | 0:84e4649e7707 | 111 | lcd_config.lcd_edge = DisplayBase::EDGE_RISING; |
1050186 | 4:138b18a6ac7b | 112 | #if(LCD_MODE) //SYNC Mode |
1050186 | 4:138b18a6ac7b | 113 | lcd_config.h_toatal_period = (LCD_H_BACK_PORCH + LCD_H_WIDTH + LCD_H_FRONT_PORCH); |
1050186 | 4:138b18a6ac7b | 114 | lcd_config.v_toatal_period = (LCD_V_BACK_PORCH + LCD_V_WIDTH + LCD_V_FRONT_PORCH); |
1050186 | 4:138b18a6ac7b | 115 | |
1050186 | 4:138b18a6ac7b | 116 | lcd_config.h_disp_widht = (LCD_H_WIDTH); |
1050186 | 4:138b18a6ac7b | 117 | lcd_config.v_disp_widht = (LCD_V_WIDTH); |
1050186 | 4:138b18a6ac7b | 118 | lcd_config.h_back_porch = (LCD_H_BACK_PORCH); |
1050186 | 4:138b18a6ac7b | 119 | lcd_config.v_back_porch = (LCD_V_BACK_PORCH); |
1050186 | 4:138b18a6ac7b | 120 | |
1050186 | 4:138b18a6ac7b | 121 | lcd_config.h_sync_port = DisplayBase::LCD_TCON_PIN_2; |
1050186 | 4:138b18a6ac7b | 122 | lcd_config.h_sync_port_polarity = DisplayBase::SIG_POL_INVERTED; |
1050186 | 4:138b18a6ac7b | 123 | lcd_config.h_sync_width = LCD_H_SYNC_WIDTH; |
1050186 | 4:138b18a6ac7b | 124 | |
1050186 | 4:138b18a6ac7b | 125 | lcd_config.v_sync_port = DisplayBase::LCD_TCON_PIN_0; |
1050186 | 4:138b18a6ac7b | 126 | lcd_config.v_sync_port_polarity = DisplayBase::SIG_POL_INVERTED; |
1050186 | 4:138b18a6ac7b | 127 | lcd_config.v_sync_width = LCD_V_SYNC_WIDTH; |
1050186 | 4:138b18a6ac7b | 128 | |
1050186 | 4:138b18a6ac7b | 129 | lcd_config.de_port = DisplayBase::LCD_TCON_PIN_3; |
1050186 | 4:138b18a6ac7b | 130 | lcd_config.de_port_polarity = DisplayBase::SIG_POL_NOT_INVERTED; |
1050186 | 4:138b18a6ac7b | 131 | #else //DE Mode |
1050186 | 4:138b18a6ac7b | 132 | lcd_config.h_toatal_period = (LCD_H_WIDTH + 80u); |
1050186 | 4:138b18a6ac7b | 133 | lcd_config.v_toatal_period = (LCD_V_WIDTH); |
1050186 | 0:84e4649e7707 | 134 | |
1050186 | 4:138b18a6ac7b | 135 | lcd_config.h_disp_widht = (LCD_H_WIDTH); |
1050186 | 4:138b18a6ac7b | 136 | lcd_config.v_disp_widht = (LCD_V_WIDTH); |
1050186 | 4:138b18a6ac7b | 137 | lcd_config.h_back_porch = (68u); |
1050186 | 4:138b18a6ac7b | 138 | lcd_config.v_back_porch = (18u); |
1050186 | 0:84e4649e7707 | 139 | |
1050186 | 0:84e4649e7707 | 140 | lcd_config.h_sync_port = DisplayBase::LCD_TCON_PIN_NON; |
1050186 | 0:84e4649e7707 | 141 | lcd_config.h_sync_port_polarity = DisplayBase::SIG_POL_NOT_INVERTED; |
1050186 | 0:84e4649e7707 | 142 | lcd_config.h_sync_width = 0; |
1050186 | 0:84e4649e7707 | 143 | |
1050186 | 0:84e4649e7707 | 144 | lcd_config.v_sync_port = DisplayBase::LCD_TCON_PIN_NON; |
1050186 | 0:84e4649e7707 | 145 | lcd_config.v_sync_port_polarity = DisplayBase::SIG_POL_NOT_INVERTED; |
1050186 | 0:84e4649e7707 | 146 | lcd_config.v_sync_width = 0; |
1050186 | 0:84e4649e7707 | 147 | |
1050186 | 0:84e4649e7707 | 148 | lcd_config.de_port = DisplayBase::LCD_TCON_PIN_3; |
1050186 | 4:138b18a6ac7b | 149 | lcd_config.de_port_polarity = DisplayBase::SIG_POL_INVERTED; |
1050186 | 4:138b18a6ac7b | 150 | #endif |
1050186 | 0:84e4649e7707 | 151 | |
1050186 | 0:84e4649e7707 | 152 | /* Graphics initialization process */ |
1050186 | 0:84e4649e7707 | 153 | error = Display.Graphics_init(&lcd_config); |
1050186 | 0:84e4649e7707 | 154 | if (error != DisplayBase::GRAPHICS_OK) { |
1050186 | 0:84e4649e7707 | 155 | printf("Line %d, error %d\n", __LINE__, error); |
1050186 | 0:84e4649e7707 | 156 | while (1); |
1050186 | 0:84e4649e7707 | 157 | } |
1050186 | 0:84e4649e7707 | 158 | |
1050186 | 0:84e4649e7707 | 159 | /* Interrupt callback function setting (Vsync signal output from scaler 0) */ |
1050186 | 0:84e4649e7707 | 160 | error = Display.Graphics_Irq_Handler_Set(DisplayBase::INT_TYPE_S0_LO_VSYNC, 0, IntCallbackFunc_Vsync); |
1050186 | 0:84e4649e7707 | 161 | if (error != DisplayBase::GRAPHICS_OK) { |
1050186 | 0:84e4649e7707 | 162 | printf("Line %d, error %d\n", __LINE__, error); |
1050186 | 0:84e4649e7707 | 163 | while (1); |
1050186 | 0:84e4649e7707 | 164 | } |
1050186 | 0:84e4649e7707 | 165 | |
1050186 | 0:84e4649e7707 | 166 | Display.Graphics_Lvds_Port_Init(lvds_pin, 8); |
1050186 | 0:84e4649e7707 | 167 | rect.vs = 0; |
1050186 | 4:138b18a6ac7b | 168 | rect.vw = LCD_V_WIDTH; |
1050186 | 0:84e4649e7707 | 169 | rect.hs = 0; |
1050186 | 4:138b18a6ac7b | 170 | rect.hw = LCD_H_WIDTH; |
1050186 | 0:84e4649e7707 | 171 | |
1050186 | 0:84e4649e7707 | 172 | Display.Graphics_Read_Setting( |
1050186 | 0:84e4649e7707 | 173 | DisplayBase::GRAPHICS_LAYER_0, |
1050186 | 4:138b18a6ac7b | 174 | (void *)frame_buffer_info.buffer_address[0], |
1050186 | 0:84e4649e7707 | 175 | FRAME_BUFFER_STRIDE, |
1050186 | 0:84e4649e7707 | 176 | DisplayBase::GRAPHICS_FORMAT_RGB565, |
1050186 | 0:84e4649e7707 | 177 | DisplayBase::WR_RD_WRSWA_32_16BIT, |
1050186 | 0:84e4649e7707 | 178 | &rect |
1050186 | 0:84e4649e7707 | 179 | ); |
1050186 | 0:84e4649e7707 | 180 | |
1050186 | 0:84e4649e7707 | 181 | /* Display Top Screen */ |
dkato | 2:c7faef0ef374 | 182 | Set_RGAObject(&frame_buffer_info); |
1050186 | 4:138b18a6ac7b | 183 | Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_0); |
1050186 | 4:138b18a6ac7b | 184 | lcd_cntrst.write(1.0); |
1050186 | 0:84e4649e7707 | 185 | |
1050186 | 4:138b18a6ac7b | 186 | graphics_matrix_float_t work_angle = 0; |
1050186 | 0:84e4649e7707 | 187 | while (1) { |
1050186 | 4:138b18a6ac7b | 188 | gyro.read(&gx, &gy, &gz); |
1050186 | 4:138b18a6ac7b | 189 | gz = gz * 0.146; //gz = [dps]. One loop is about 146ms(process[10ms] + printf[36ms] + wait[100ms]) |
1050186 | 4:138b18a6ac7b | 190 | if ((gz >= 1) || (gz <= -1)) { |
1050186 | 4:138b18a6ac7b | 191 | /* When the sensor tilts to the right, the value becomes a negative, and the image is roteted to the right. */ |
1050186 | 4:138b18a6ac7b | 192 | /* When the sensor tilts to the left, the value becomes a active, and the image is roteted to the left. */ |
1050186 | 4:138b18a6ac7b | 193 | work_angle -= gz; |
1050186 | 4:138b18a6ac7b | 194 | work_angle = (graphics_matrix_float_t)fmod(work_angle, ROTATION_MAX_NUM); |
1050186 | 4:138b18a6ac7b | 195 | printf("acce : %f angle : %5.2f\n", gz, work_angle); |
1050186 | 0:84e4649e7707 | 196 | } |
1050186 | 4:138b18a6ac7b | 197 | /* Draw screen */ |
1050186 | 4:138b18a6ac7b | 198 | Swap_FrameBuffer(&frame_buffer_info); |
1050186 | 4:138b18a6ac7b | 199 | RGA_Func_Rotation(&frame_buffer_info, work_angle); |
1050186 | 4:138b18a6ac7b | 200 | Update_LCD_Display(&frame_buffer_info); |
1050186 | 0:84e4649e7707 | 201 | Thread::wait(100); |
1050186 | 0:84e4649e7707 | 202 | } |
1050186 | 0:84e4649e7707 | 203 | } |