Renesas GR-Peach LCD Interface
Dependencies: EthernetInterface HTTPD PubNub SDFileSystem mbed-rtos mbed picojson
Renesas GR-Peach LCD Interface
Diff: lcd_main.cpp
- Revision:
- 0:0b32d3eaabfe
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lcd_main.cpp Fri Oct 23 20:16:05 2015 +0000 @@ -0,0 +1,647 @@ +#include "gen_helper.h" +#include "math.h" + + +/* An SPI Master for interfacing and handling an LCD Slave with GR-Peach */ + + +/* Variables for holding previously drawn co-ordinate values */ +int x_left = 0; //holder for the last updated x co-ordinate value for the left side +int y_left = 0; //holder for the last updated y co-ordinate value for the left side +int x_right = 0; //holder for the last updated x co-ordinate value for the right side +int y_right = 0; //holder for the last updated y co-ordinate value for the right side + +//The number of the levels for the tree. +//This is declared here for ease of change in any function and reset it to +//the original value after use. +int number_levels = 0; + +gen_helper::gen_helper(PinName MOSI, PinName MISO, PinName SCK, PinName CS, PinName Reset, PinName RS, PinName _USBTX, PinName _USBRX, PwmOut _pwm) : + lcd(MOSI, MISO, SCK), ssel(CS), reset(Reset), rs(RS), console(_USBTX, _USBRX), pwm(_pwm) +{ + _height = SCREEN_HEIGHT; + _width = SCREEN_WIDTH; +} + + +/* Init console by setting the baud rate */ + +void gen_helper::init_console() +{ + //init serial over USB here + console.baud(115200); + console.printf("Console init done\n"); +} + +/** + * Draws a line by a factor of lambda value + *(x0,y0) are initial co-ordinates and (x1,y1) are the end co-ordinates + + * x0 - starting x co-ordinate value + * y0 - starting y co-ordinate value + * x1 - end x co-ordinate value + * y1 - end y co-ordinate value + * lambda - the factor that decides the length of the resulting line segment + */ +void gen_helper::massaged_line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, float lambda, uint16_t colour, uint16_t *X, uint16_t *Y) +{ + *X = (uint16_t)(x0 + (lambda * (x1 - x0))); + *Y = (uint16_t)(y0 + (lambda * (y1 - y0))); +} + + +/** + * rotate (x2,y2) around (x1,y1) by alpha degrees + * combines rotation and translation also. + + * x1 - starting x co-ordinate + * y1 - starting y co-ordinate + * x2 - end x co-ordinate + * y2 - end y co-ordinate + * alpha - the degree of rotation required + */ +void gen_helper::rotate_line(float x1, float y1, float x2, float y2, uint16_t alpha, float *X, float *Y) +{ + float radian = (3.1415 * alpha / 180); + *X = (x2 - x1) * cosf(radian) - (y2 - y1) * sinf(radian) + x1; + *Y = (y2 - y1) * cosf(radian) + (x2 - x1) * sinf(radian) + y1; +} + + +/** + * Draw a line with the init and end co-ordinates + * (x0, y0) - start co-ordinates + * (x1, y1) - end co-ordinates + * color - color of the line + * Based on the ST7735 source +*/ +void gen_helper::drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y1,uint16_t color) +{ + int16_t x, y; + float slope; + + //check for slope conditions + if( (x0 != x1) && (y0 != y1) ) + { + slope = (y1 - y0) / (x1 - x0); + + if (abs(slope) < 1) + { + for(x = x0; x < x1 + 1; x++) + { + y = (x - x0) * slope + y0; + draw_pixel(x, (y + 0.5), color); + } + } + else + { + for(y = y0; y < y1 + 1; y++) + { + x = (y - y0) / slope + x0; + draw_pixel((x + 0.5), y, color); + } + } + } +} + +/** + * A helper function which is flexible enough to be + * given any pattern to be drawn on the LCD + * initial values are (20,0) and (20,20) and the number of levels in 7 + */ +void gen_helper::draw_pattern_helper() +{ + int first_x0 = 20; + int first_y0 = 0; + int first_x1 = 20; + int first_y1 = 20; + //set the number of levels of the tree to 7 + number_levels = 7; + + //Draw the first tree + draw_custom_pattern(first_x0, first_y0, first_x1, first_y1); + + + //The second tree in the same plane + int next_tree_index = first_x0 + 30; + first_x0 = next_tree_index; + first_x1 = first_x0; + + draw_custom_pattern(first_x0, first_y0, first_x1, first_y1); + + //Third tree + next_tree_index += 30; + first_x0 = next_tree_index; + first_x1 = first_x0; + draw_custom_pattern(first_x0, first_y0, first_x1, first_y1); + + //Fourth tree + next_tree_index += 30; + first_x0 = next_tree_index; + first_x1 = first_x0; + draw_custom_pattern(first_x0, first_y0, first_x1, first_y1); + + //Fifth tree which starts at a much higher level than the previous trees + next_tree_index = 35; + first_x0 = next_tree_index; + first_x1 = first_x0; + first_y0+=20; + first_y1+=20; + draw_custom_pattern(first_x0, first_y0, first_x1, first_y1); + + //Sixth tree that is at the same level as fifth + next_tree_index = 65; + first_x0 = next_tree_index; + first_x1 = first_x0; + draw_custom_pattern(first_x0, first_y0, first_x1, first_y1); + + //Seventh tree that is at the same level as sixth + next_tree_index = 95; + first_x0 = next_tree_index; + first_x1 = first_x0; + draw_custom_pattern(first_x0, first_y0, first_x1, first_y1); + + + //Eighth tree at the same level as seventh + next_tree_index = 20; + first_x0 = next_tree_index; + first_x1 = first_x0; + first_y0 = 90; + first_y1 = first_y0 + 20; + number_levels = 3; + draw_custom_pattern(first_x0, first_y0, first_x1, first_y1); + + //Ninth tree at the same level as eight but with only 3 levels + next_tree_index = 50; + first_x0 = next_tree_index; + first_x1 = first_x0; + first_y0 = 90; + first_y1 = first_y0 + 20; + number_levels = 3; + draw_custom_pattern(first_x0, first_y0, first_x1, first_y1); + + //Tenth tree at the same level as ninth but with only 3 levels + next_tree_index = 80; + first_x0 = next_tree_index; + first_x1 = first_x0; + first_y0 = 90; + first_y1 = first_y0 + 20; + number_levels = 3; + draw_custom_pattern(first_x0, first_y0, first_x1, first_y1); + + //Eleventh tree at the same level as tenth but with only 3 levels + next_tree_index = 110; + first_x0 = next_tree_index; + first_x1 = first_x0; + first_y0 = 90; + first_y1 = first_y0 + 20; + number_levels = 3; + draw_custom_pattern(first_x0, first_y0, first_x1, first_y1); + +} + + +/** + * Draw the forest in any pattern that is desired with + * given two sets of start and end points + + * x0 - starting x co-ordinate value + * y0 - starting y co-ordinate value + * x1 - end x co-ordinate value + * y1 - end y co-ordinate value + * + */ +void gen_helper::draw_custom_pattern(int x0, int y0, int x1, int y1) +{ + int first_x0 = x0; + int first_y0 = y0; + int first_x1 = x1; + int first_y1 = y1; + int temp_leftx = 0; + int temp_lefty = 0; + int temp_rightx = 0; + int temp_righty = 0; + int r_temp_leftx = 0; + int r_temp_lefty = 0; + int r_temp_rightx = 0; + int r_temp_righty = 0; + + //draw the initial trunk of the tree and the next vertical branch that is + //a shrunken version of the trunk + drawLine(first_x0, first_y0, first_x1, first_y0+10, BLACK); + drawLine(first_x0+1, first_y0, first_x1+1, first_y0+10, BLACK); + draw_pattern(first_x0, first_y0+10, first_x1, first_y1+10); + + + //The pattern for drawing the tree and hence the forest. + //This can be any pattern required. + temp_leftx = x_left; + temp_lefty = y_left; + temp_rightx = x_right; + temp_righty = y_right; + + r_temp_leftx = x_left; + r_temp_lefty = y_left; + r_temp_rightx = x_right; + r_temp_righty = y_right; + + + int i = 0; + for(i = 0; i < number_levels; i++) + { + draw_pattern(r_temp_leftx, r_temp_lefty, r_temp_leftx, r_temp_lefty+10); + draw_pattern(r_temp_rightx, r_temp_righty, r_temp_rightx, r_temp_righty+10); + r_temp_leftx = x_left; + r_temp_lefty = y_left; + r_temp_rightx = x_right; + r_temp_righty = y_right; + } + + i = 0; + for(i = 0; i < number_levels; i++) + { + draw_pattern(temp_rightx, temp_righty, temp_rightx, temp_righty+10); + draw_pattern(temp_leftx, temp_lefty, temp_leftx, temp_lefty+10); + temp_leftx = x_left; + temp_lefty = y_left; + temp_rightx = x_right; + temp_righty = y_right; + } + +} + + +/** + * + * x1 - starting x co-ordinate value + * y1 - starting y co-ordinate value + * x2 - end x co-ordinate value + * y2 - end y co-ordinate value + */ +void gen_helper::draw_pattern(int x1, int y1, int x2, int y2) +{ + + int first_x0 = x1; + int first_y0 = y1; + int first_x1 = x2; + int first_y1 = y2; + int alpha = 30; + int neg_alpha = -30; + + + float x0=0, y0=0; + + rotate_line(first_x0, first_y0, first_x1, first_y1, alpha, &x0, &y0); + + drawLine(first_x0, first_y0, (int)x0, (int)y0, GREEN); + + x_right = (int)x0; + y_right = (int)y0; + + x0 = 0; + y0 = 0; + + rotate_line(first_x0, first_y0, first_x1, first_y1, neg_alpha, &x0, &y0); + drawLine(first_x0, first_y0, (int)(x0+3), (int)y0, GREEN); + + x_left = (int)x0+3; + y_left = (int)y0; + + +} + +/********* SD card helper functions; wrappers over the SD card file system ********/ +uint8_t gen_helper::init_disk() +{ + return sd_fs->disk_initialize(); +} + +/** +* Initialize the SD card +*/ +uint8_t gen_helper::init_SD() +{ + sd_fs = new SDFileSystem(P8_5, P8_6, P8_3, P8_4, "sd"); + + if(sd_fs) + return (uint8_t)0; //force a casting + else + return (uint8_t)-1; +} + +/** +* Open a file and return the file descriptor +*/ +FILE* gen_helper::open_file(char *path, char *mode) +{ + return fopen(path, mode); +} + +uint8_t gen_helper::close_file(FILE *fp) +{ + return fclose(fp); +} + +uint8_t gen_helper::make_dir(char *path, uint32_t mode) +{ + return mkdir(path, mode); +} + +uint8_t gen_helper::remove_file(char *path) +{ + return remove(path); +} +/****SD card function implementations end****/ + + +/* Initialize the LCD +* +*TODO : Check the row select and col select for Renesas GR-PEACH +* +* Based on the specs from ST7735 +*/ +void gen_helper::lcd_init() +{ + console.printf("Writing to the lcd \n"); + + lcd.format(8, 3); + //lcd.frequency(15000000); + ssel = 0; + reset = 1; + wait_ms(500); + reset = 0; + wait_ms(500); + reset = 1; + wait_ms(500); + + write_spi_command(SW_RESET); // SW Reset + wait_ms(150); + write_spi_command(AWAKE_SLEEPMODE); // Out of sleepmode + wait_ms(500); + + write_spi_command(FRAMERATE_NORMAL); // Frame rate in normal mode + write_spi_data(0x01); + write_spi_data(0x2C); + write_spi_data(0x2D); + + write_spi_command(FRAMERATE_IDLE); // Frame rate in idle mode + write_spi_data(0x01); + write_spi_data(0x2C); + write_spi_data(0x2D); + + write_spi_command(FRAMERATE_PARTIAL); // Frame rate in partial mode + write_spi_data(0x01); + write_spi_data(0x2C); + write_spi_data(0x2D); + write_spi_data(0x01); // inversion mode settings + write_spi_data(0x2C); + write_spi_data(0x2D); + + write_spi_command(INVERTED_MODE_OFF); // Inverted mode off + write_spi_data(0x07); + + write_spi_command(POWER_CONTROL_1); + write_spi_data(0xA2); + write_spi_data(0x02); + write_spi_data(0x84); + + write_spi_command(POWER_CONTROL_2); // POWER CONTROL 2 + write_spi_data(0xC5); + + write_spi_command(POWER_CONTROL_3); // POWER CONTROL 3 + write_spi_data(0x0A); + write_spi_data(0x00); + + write_spi_command(POWER_CONTROL_4); // POWER CONTROL 4 + write_spi_data(0x8A); + write_spi_data(0x2A); + + write_spi_command(POWER_CONTROL_5); // POWER CONTROL 5 + write_spi_data(0x8A); + write_spi_data(0xEE); + + write_spi_command(POWER_CONTROL_6); // POWER CONTROL 6 + write_spi_data(0x0E); + + write_spi_command(INVOFF); + + write_spi_command(ORIENTATION); // ORIENTATION + write_spi_data(0xC8); + + write_spi_command(COLOR_MODE); + write_spi_data(0x05); + + write_spi_command(COLUMN_ADDR_SET); + write_spi_data(0x00); + write_spi_data(0x00); + write_spi_data(0x00); + write_spi_data(0x7F); + + write_spi_command(ROW_ADDR_SET); // ROW ADDR SET + write_spi_data(0x00); + write_spi_data(0x00); + write_spi_data(0x00); + write_spi_data(0x9F); + + + write_spi_command(0xE0); + write_spi_data(0x02); + write_spi_data(0x1c); + write_spi_data(0x07); + write_spi_data(0x12); + write_spi_data(0x37); + write_spi_data(0x32); + write_spi_data(0x29); + write_spi_data(0x2d); + write_spi_data(0x29); + write_spi_data(0x25); + write_spi_data(0x2B); + write_spi_data(0x39); + write_spi_data(0x00); + write_spi_data(0x01); + write_spi_data(0x03); + write_spi_data(0x10); + write_spi_command(0xE1); + write_spi_data(0x03); + write_spi_data(0x1d); + write_spi_data(0x07); + write_spi_data(0x06); + write_spi_data(0x2E); + write_spi_data(0x2C); + write_spi_data(0x29); + write_spi_data(0x2D); + write_spi_data(0x2E); + write_spi_data(0x2E); + write_spi_data(0x37); + write_spi_data(0x3F); + write_spi_data(0x00); + write_spi_data(0x00); + write_spi_data(0x02); + write_spi_data(0x10); + + write_spi_command(DISPLAY_ON); // display ON + wait_ms(100); + + write_spi_command(NORMAL_DISP_ON); // normal display on + wait_ms(10); + + pwm.period_ms(2); + + // just increasing the brightness of the screen gradually + for(float i = 0.0f; i < 1.0f; i += 0.1f) + { + wait_ms(200); + pwm = i; + } + + console.printf("PWM done\n"); // here for debugging + +} + +inline int gen_helper::spiwrite(uint8_t c) +{ + return lcd.write(c); + +} + +/* Write command */ +void gen_helper::write_spi_command(uint8_t c) +{ + + rs = 0; + ssel = 0; + lcd.write(c); + ssel = 1; +} + +/* Write data */ +void gen_helper::write_spi_data(uint8_t c) +{ + + rs = 1; + ssel = 0; + lcd.write(c); + ssel = 1; + +} + +/** + * Based on ST7735 source ; sets the screen co-ordinates +*/ +void gen_helper::set_screen_coor(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) +{ + + write_spi_command(COLUMN_ADDR_SET); // Column addr set + write_spi_data(0x00); + write_spi_data(x0+colstart); // XSTART + write_spi_data(0x00); + write_spi_data(x1+colstart); // XEND + + write_spi_command(ROW_ADDR_SET); // Row addr set + write_spi_data(0x00); + write_spi_data(y0+rowstart); // YSTART + write_spi_data(0x00); + write_spi_data(y1+rowstart); // YEND + + write_spi_command(WRITE_RAM); // write to RAM +} + + +/** +* Draw a pixel on the screen +*/ +void gen_helper::draw_pixel(int16_t x, int16_t y, uint16_t color) { + + // exit if the co-ordinates are out of bounds of the screen + if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) + return; + + set_screen_coor(x, y, x + 1, y + 1); + + rs = 1; + ssel = 0; + lcd.format(16,3); //set the data rate to 16 bits + lcd.write(color); + ssel = 1; + lcd.format(8,3); //set the data rate to 8 bits +} + +/** +* Draw a vertical line +* Based on ST7735 source +*/ +void gen_helper::draw_vertical_line(int16_t x, int16_t y, int16_t h, uint16_t color) +{ + + if((x >= _width) || (y >= _height)) + return; + + if((y + h - 1) >= _height) + h = _height - y; + + set_screen_coor(x, y, x, y + h - 1); + + uint8_t hi = color >> 8, lo = color; + while (h--) + { + spiwrite(hi); + spiwrite(lo); + } +} + +/** +* Draw a horizontal line +* Based on ST7735 source +*/ +void gen_helper::draw_horizontal_line(int16_t x, int16_t y, int16_t w, uint16_t color) +{ + + //check for screen boundary + if((x >= _width) || (y >= _height)) + return; + + if((x + w - 1) >= _width) + w = _width - x; + + set_screen_coor(x, y, x + w - 1, y); + + uint8_t hi = color >> 8, lo = color; + + while (w--) { + spiwrite(hi); + spiwrite(lo); + } +} + +/** +* Draw a rectangle and fill it with a color +*/ +void gen_helper::fill_rect(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint32_t color) +{ + int16_t width, height; + + width = x1 - x0 + 1; + height = y1 - y0 + 1; + set_screen_coor(x0, y0, x1, y1); + write_spi_command(WRITE_RAM); + write_rgb(color, width * height); +} + +/** +* Write RGB colors to the screen +*/ +void gen_helper::write_rgb(uint32_t color, uint32_t repeat) { + + uint8_t red, green, blue; + int i; + red = (color >> 16); + green = (color >> 8) & 0xFF; + blue = color & 0xFF; + + for (i = 0; i< repeat; i++) + { + write_spi_data(red); + write_spi_data(green); + write_spi_data(blue); + } +} \ No newline at end of file