Library to control the EM027BS013 ePaper display from Pervasive Display.
Dependents: app_epaper_EM027BS013_LPC1549 lpc4088_ebb_epaper EaEpaper_EM027BS013 app_epaper_EM027BS013 ... more
EPD_COG_process_v230_G2.cpp
00001 /** 00002 * \file 00003 * 00004 * \brief The waveform driving processes and updating stages of G2 COG with V230 EPD 00005 * 00006 * Copyright (c) 2012-2014 Pervasive Displays Inc. All rights reserved. 00007 * 00008 * \asf_license_start 00009 * 00010 * \page License 00011 * 00012 * Redistribution and use in source and binary forms, with or without 00013 * modification, are permitted provided that the following conditions are met: 00014 * 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 00018 * 2. Redistributions in binary form must reproduce the above copyright notice, 00019 * this list of conditions and the following disclaimer in the documentation 00020 * and/or other materials provided with the distribution. 00021 * 00022 * 3. The name of Atmel may not be used to endorse or promote products derived 00023 * from this software without specific prior written permission. 00024 * 00025 * 4. This software may only be redistributed and used in connection with an 00026 * Atmel microcontroller product. 00027 * 00028 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED 00029 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00030 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE 00031 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR 00032 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00033 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00034 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00035 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 00036 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00037 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00038 * POSSIBILITY OF SUCH DAMAGE. 00039 * 00040 * \asf_license_stop 00041 **/ 00042 00043 #include "EPD_COG_process.h" 00044 #ifdef COG_V230_G2 00045 00046 #define ADDRESS_NULL 0xffffffff 00047 //EPD Panel parameters 00048 const struct COG_parameters_t COG_parameters[COUNT_OF_EPD_TYPE] = { 00049 { 00050 // FOR 1.44" 00051 {0x00,0x00,0x00,0x00,0x00,0x0F,0xFF,0x00}, 00052 0x03, 00053 (128/8), 00054 96, 00055 ((((128+96)*2)/8)+1), 00056 0, 00057 480 00058 }, 00059 { 00060 // For 2.0" 00061 {0x00,0x00,0x00,0x00,0x01,0xFF,0xE0,0x00}, 00062 0x03, 00063 (200/8), 00064 96, 00065 ((((200+96)*2)/8)+1), 00066 0, 00067 480 00068 }, 00069 { 00070 // For 2.7" 00071 {0x00,0x00,0x00,0x7F,0xFF,0xFE,0x00,0x00}, 00072 0x00, 00073 (264/8), 00074 176, 00075 ((((264+176)*2)/8)+1), 00076 0, 00077 630 00078 } 00079 }; 00080 00081 /* \brief EPD Waveform parameters 00082 * \note the parameters of waveform table below is different from the G2 COG document due to 00083 * use block size is easier to achieve than accurate block time for different MCU. 00084 * The approach is also working. 00085 * */ 00086 const struct EPD_WaveformTable_Struct E_Waveform[COUNT_OF_EPD_TYPE][3] = { 00087 {// FOR 1.44" 00088 {//50 �� T �� 40 00089 4, //stage1_frame1 00090 16, //stage1_block1 00091 2, //stage1_step1 00092 155, //stage2_t1 00093 155, //stage2_t2 00094 4, //stage2_cycle 00095 4, //stage3_frame3 00096 16, //stage3_block3 00097 2 //stage3_step3 00098 } 00099 ,{//40 �� T �� 10 00100 4, //stage1_frame1 00101 16, //stage1_block1 00102 2, //stage1_step1 00103 155, //stage2_t1 00104 155, //stage2_t2 00105 4, //stage2_cycle 00106 4, //stage3_frame3 00107 16, //stage3_block3 00108 2 //stage3_step3 00109 }, 00110 {//10 �� T �� 0 00111 2, //stage1_frame1 00112 42, //stage1_block1 00113 6, //stage1_step1 00114 392, //stage2_t1 00115 392, //stage2_t2 00116 4, //stage2_cycle 00117 2, //stage3_frame3 00118 42, //stage3_block3 00119 6 //stage3_step3 00120 } 00121 00122 }, 00123 {// For 2.0" 00124 {//50 �� T �� 40 00125 4, //stage1_frame1 00126 36, //stage1_block1 00127 2, //stage1_step1 00128 196, //stage2_t1 00129 196, //stage2_t2 00130 4, //stage2_cycle 00131 4, //stage3_frame3 00132 36, //stage3_block3 00133 2 //stage3_step3 00134 }, 00135 {//40 �� T �� 10 00136 2, //stage1_frame1 00137 36, //stage1_block1 00138 2, //stage1_step1 00139 196, //stage2_t1 00140 196, //stage2_t2 00141 4, //stage2_cycle 00142 2, //stage3_frame3 00143 36, //stage3_block3 00144 2 //stage3_step3 00145 }, 00146 {//10 �� T �� 0 00147 2, //stage1_frame1 00148 36, //stage1_block1 00149 2, //stage1_step1 00150 392, //stage2_t1 00151 392, //stage2_t2 00152 4, //stage2_cycle 00153 2, //stage3_frame3 00154 36, //stage3_block3 00155 2 //stage3_step3 00156 } 00157 }, 00158 {// For 2.7" 00159 {//50 �� T �� 40 00160 4, //stage1_frame1 00161 28, //stage1_block1 00162 4, //stage1_step1 00163 196, //stage2_t1 00164 196, //stage2_t2 00165 4, //stage2_cycle 00166 4, //stage3_frame3 00167 28, //stage3_block3 00168 4 //stage3_step3 00169 }, 00170 {//40 �� T �� 10 00171 2, //stage1_frame1 00172 28, //stage1_block1 00173 2, //stage1_step1 00174 196, //stage2_t1 00175 196, //stage2_t2 00176 4, //stage2_cycle 00177 2, //stage3_frame3 00178 28, //stage3_block3 00179 2 //stage3_step3 00180 }, 00181 {//10 �� T �� 0 00182 2, //stage1_frame1 00183 28, //stage1_block1 00184 4, //stage1_step1 00185 392, //stage2_t1 00186 392, //stage2_t2 00187 4, //stage2_cycle 00188 2, //stage3_frame3 00189 28, //stage3_block3 00190 4 //stage3_step3 00191 } 00192 }, 00193 00194 }; 00195 00196 const uint8_t SCAN_TABLE[4] = {0xC0,0x30,0x0C,0x03}; 00197 00198 static struct EPD_WaveformTable_Struct *action__Waveform_param; 00199 static COG_line_data_packet_type COG_Line; 00200 static EPD_read_flash_handler _On_EPD_read_flash; 00201 static uint8_t *data_line_even; 00202 static uint8_t *data_line_odd; 00203 static uint8_t *data_line_scan; 00204 static uint8_t *data_line_border_byte; 00205 00206 /** 00207 * \brief According to EPD size and temperature to get stage_time 00208 * \note Refer to COG document Section 5.3 for more details 00209 * 00210 * \param EPD_type_index The defined EPD size 00211 */ 00212 static void set_temperature_factor(uint8_t EPD_type_index) { 00213 int8_t temperature; 00214 temperature = get_temperature(); 00215 if (50 >= temperature && temperature > 40){ 00216 action__Waveform_param=(struct EPD_WaveformTable_Struct *)&E_Waveform[EPD_type_index][0]; 00217 }else if (40 >= temperature && temperature > 10){ 00218 action__Waveform_param=(struct EPD_WaveformTable_Struct *)&E_Waveform[EPD_type_index][1]; 00219 }else if (10 >= temperature && temperature > 0){ 00220 action__Waveform_param=(struct EPD_WaveformTable_Struct *)&E_Waveform[EPD_type_index][2]; 00221 }else action__Waveform_param=(struct EPD_WaveformTable_Struct *)&E_Waveform[EPD_type_index][1]; //Default 00222 } 00223 00224 /** 00225 * \brief Initialize the EPD hardware setting 00226 */ 00227 void EPD_init(void) { 00228 EPD_display_hardware_init(); 00229 EPD_cs_low(); 00230 EPD_rst_low(); 00231 EPD_discharge_low(); 00232 EPD_border_low(); 00233 } 00234 00235 /** 00236 * \brief Select the EPD size to get line data array for driving COG 00237 * 00238 * \param EPD_type_index The defined EPD size 00239 */ 00240 void COG_driver_EPDtype_select(uint8_t EPD_type_index) { 00241 switch(EPD_type_index) { 00242 case EPD_144: 00243 data_line_even = &COG_Line.line_data_by_size.line_data_for_144.even[0]; 00244 data_line_odd = &COG_Line.line_data_by_size.line_data_for_144.odd[0]; 00245 data_line_scan = &COG_Line.line_data_by_size.line_data_for_144.scan[0]; 00246 data_line_border_byte = &COG_Line.line_data_by_size.line_data_for_144.border_byte; 00247 break; 00248 case EPD_200: 00249 data_line_even = &COG_Line.line_data_by_size.line_data_for_200.even[0]; 00250 data_line_odd = &COG_Line.line_data_by_size.line_data_for_200.odd[0]; 00251 data_line_scan = &COG_Line.line_data_by_size.line_data_for_200.scan[0]; 00252 data_line_border_byte = &COG_Line.line_data_by_size.line_data_for_200.border_byte; 00253 break; 00254 case EPD_270: 00255 data_line_even = &COG_Line.line_data_by_size.line_data_for_270.even[0]; 00256 data_line_odd = &COG_Line.line_data_by_size.line_data_for_270.odd[0]; 00257 data_line_scan = &COG_Line.line_data_by_size.line_data_for_270.scan[0]; 00258 data_line_border_byte = &COG_Line.line_data_by_size.line_data_for_270.border_byte; 00259 break; 00260 } 00261 } 00262 00263 /** 00264 * \brief Power on COG Driver 00265 * \note For detailed flow and description, please refer to the COG G2 document Section 3. 00266 */ 00267 void EPD_power_on (void) { 00268 /* Initial state */ 00269 EPD_Vcc_turn_on(); //Vcc and Vdd >= 2.7V 00270 EPD_cs_high(); 00271 EPD_border_high(); 00272 EPD_rst_high(); 00273 delay_ms(5); 00274 EPD_rst_low(); 00275 delay_ms(5); 00276 EPD_rst_high(); 00277 delay_ms(5); 00278 } 00279 00280 00281 /** 00282 * \brief Initialize COG Driver 00283 * \note For detailed flow and description, please refer to the COG G2 document Section 4. 00284 * 00285 * \param EPD_type_index The defined EPD size 00286 */ 00287 uint8_t EPD_initialize_driver (uint8_t EPD_type_index) { 00288 00289 uint16_t i; 00290 // Empty the Line buffer 00291 for (i = 0; i <= LINE_BUFFER_DATA_SIZE; i ++) { 00292 COG_Line.uint8[i] = 0x00; 00293 } 00294 // Determine the EPD size for driving COG 00295 COG_driver_EPDtype_select(EPD_type_index); 00296 00297 // Sense temperature to determine Temperature Factor 00298 set_temperature_factor(EPD_type_index); 00299 i = 0; 00300 00301 while (EPD_IsBusy()) { 00302 if((i++) >= 0x0FFF) return ERROR_BUSY; 00303 } 00304 00305 //Check COG ID 00306 if((SPI_R(0x72,0x00) & 0x0f) !=0x02) return ERROR_COG_ID; 00307 00308 //Disable OE 00309 epd_spi_send_byte(0x02,0x40); 00310 00311 //Check Breakage 00312 if((SPI_R(0x0F,0x00) & 0x80) != 0x80) return ERROR_BREAKAGE; 00313 00314 //Power Saving Mode 00315 epd_spi_send_byte(0x0B, 0x02); 00316 00317 //Channel Select 00318 epd_spi_send (0x01, (uint8_t *)&COG_parameters[EPD_type_index].channel_select, 8); 00319 00320 //High Power Mode Osc Setting 00321 epd_spi_send_byte(0x07,0xD1); 00322 00323 //Power Setting 00324 epd_spi_send_byte(0x08,0x02); 00325 00326 //Set Vcom level 00327 epd_spi_send_byte(0x09,0xC2); 00328 00329 //Power Setting 00330 epd_spi_send_byte(0x04,0x03); 00331 00332 //Driver latch on 00333 epd_spi_send_byte(0x03,0x01); 00334 00335 //Driver latch off 00336 epd_spi_send_byte(0x03,0x00); 00337 00338 delay_ms(5); 00339 00340 //Chargepump Start 00341 i=0; 00342 do { 00343 //Start chargepump positive V 00344 //VGH & VDH on 00345 epd_spi_send_byte(0x05,0x01); 00346 00347 delay_ms(240); 00348 00349 //Start chargepump neg voltage 00350 //VGL & VDL on 00351 epd_spi_send_byte(0x05,0x03); 00352 00353 delay_ms(40); 00354 00355 //Set chargepump 00356 //Vcom_Driver to ON 00357 //Vcom_Driver on 00358 epd_spi_send_byte(0x05,0x0F); 00359 00360 delay_ms(40); 00361 00362 //Check DC/DC 00363 if((SPI_R(0x0F,0x00) & 0x40) != 0x00) break; 00364 00365 }while((i++) != 4); 00366 00367 if(i>=4) 00368 { 00369 //Output enable to disable 00370 epd_spi_send_byte(0x02,0x40); 00371 return ERROR_CHARGEPUMP; 00372 } 00373 else return RES_OK; 00374 } 00375 00376 /** 00377 * \brief Initialize the parameters of Block type stage 00378 * 00379 * \param EPD_type_index The defined EPD size 00380 * \param EPD_V230_G2_Struct The Block type waveform structure 00381 * \param block_size The width of Block size 00382 * \param step_size The width of Step size 00383 * \param frame_cycle The width of Step size 00384 */ 00385 void stage_init(uint8_t EPD_type_index,struct EPD_V230_G2_Struct *S_epd_v230, 00386 uint8_t block_size,uint8_t step_size, 00387 uint8_t frame_cycle) 00388 { 00389 S_epd_v230->frame_y0 = 0; 00390 S_epd_v230->frame_y1 = 176; 00391 S_epd_v230->block_y0 = 0; 00392 S_epd_v230->block_y1 = 0; 00393 S_epd_v230->step_y0 = 0; 00394 S_epd_v230->step_y1 = 0; 00395 S_epd_v230->block_size = action__Waveform_param->stage1_block1; 00396 S_epd_v230->step_size =action__Waveform_param->stage1_step1; 00397 S_epd_v230->frame_cycle = action__Waveform_param->stage1_frame1; 00398 S_epd_v230->number_of_steps = (COG_parameters[EPD_type_index].vertical_size / S_epd_v230->step_size) + (action__Waveform_param->stage1_block1 / action__Waveform_param->stage1_step1) -1; 00399 00400 } 00401 00402 /** 00403 * \brief For Frame type waveform to update all black/white pattern 00404 * 00405 * \param EPD_type_index The defined EPD size 00406 * \param bwdata Black or White color to whole screen 00407 * \param work_time The working time 00408 */ 00409 static inline void same_data_frame (uint8_t EPD_type_index, uint8_t bwdata, uint32_t work_time) { 00410 uint16_t i; 00411 for (i = 0; i < COG_parameters[EPD_type_index].horizontal_size; i++) { 00412 data_line_even[i]=bwdata; 00413 data_line_odd[i]=bwdata; 00414 } 00415 start_EPD_timer(); 00416 do 00417 { 00418 for (i = 0; i < COG_parameters[EPD_type_index].vertical_size; i++) { 00419 00420 /* Scan byte shift per data line */ 00421 data_line_scan[(i>>2)]=SCAN_TABLE[(i%4)]; 00422 00423 /* Sending data */ 00424 epd_spi_send (0x0A, (uint8_t *)&COG_Line.uint8, COG_parameters[EPD_type_index].data_line_size); 00425 00426 /* Turn on Output Enable */ 00427 epd_spi_send_byte (0x02, 0x07); 00428 00429 data_line_scan[(i>>2)]=0; 00430 00431 } 00432 } while (get_current_time_tick()<(work_time)); 00433 /* Stop system timer */ 00434 stop_EPD_timer(); 00435 } 00436 00437 /** 00438 * \brief Write nothing Line to COG 00439 * \note A line whose all Scan Bytes are 0x00 00440 * 00441 * \param EPD_type_index The defined EPD size 00442 */ 00443 void nothing_line(uint8_t EPD_type_index) { 00444 uint16_t i; 00445 for (i = 0; i < COG_parameters[EPD_type_index].horizontal_size; i++) { 00446 data_line_even[i] = NOTHING; 00447 data_line_odd[i] = NOTHING; 00448 } 00449 } 00450 00451 00452 /** 00453 * \brief Get line data of Stage 1 and 3 00454 * 00455 * \note 00456 * - One dot/pixel is comprised of 2 bits which are White(10), Black(11) or Nothing(01). 00457 * The image data bytes must be divided into Odd and Even bytes. 00458 * - The COG driver uses a buffer to write one line of data (FIFO) - interlaced 00459 * It's different order from COG_G1 00460 * Odd byte {D(199,y),D(197,y), D(195,y), D(193,y)}, ... ,{D(7,y),D(5,y),D(3,y), D(1,y)} 00461 * Scan byte {S(96), S(95)...} 00462 * Odd byte {D(2,y),D(4,y), D(6,y), D(8,y)}, ... ,{D(194,y),D(196,y),D(198,y), D(200,y)} 00463 * - For more details on the driving stages, please refer to the COG G2 document Section 5. 00464 * 00465 * \param EPD_type_index The defined EPD size 00466 * \param image_ptr The pointer of memory that stores image that will send to COG 00467 * \param stage_no The assigned stage number that will proceed 00468 */ 00469 00470 void read_line_data_handle(uint8_t EPD_type_index,uint8_t *image_prt,uint8_t stage_no) 00471 { 00472 int16_t x,k; 00473 uint8_t temp_byte; // Temporary storage for image data check 00474 k=COG_parameters[EPD_type_index].horizontal_size-1; 00475 for (x =0 ; x < COG_parameters[EPD_type_index].horizontal_size ; x++) { 00476 temp_byte = *image_prt++; 00477 switch(stage_no) { 00478 case Stage1: // Inverse image 00479 /* Example at stage 1 to get Even and Odd data. It's different order from G1. 00480 * +---------+----+----+----+----+----+----+----+----+ 00481 * | |bit7|bit6|bit5|bit4|bit3|bit2|bit1|bit0| 00482 * |temp_byte+----+----+----+----+----+----+----+----+ 00483 * | | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 00484 * +---------+----+----+----+----+----+----+----+----+ */ 00485 data_line_odd[x] = ((temp_byte & 0x40) ? BLACK3 : WHITE3); // WHITE3 = 0x80 = 1000 0000 00486 data_line_odd[x] |= ((temp_byte & 0x10) ? BLACK2 : WHITE2); // BLACK2 = 0x30 = 0011 0000 00487 data_line_odd[x] |= ((temp_byte & 0x04) ? BLACK1 : WHITE1); // BLACK1 = 0x0C = 0000 1100 00488 data_line_odd[x] |= ((temp_byte & 0x01) ? BLACK0 : WHITE0); // WHITE0 = 0x02 = 0000 0010 00489 /* data_line_odd[x] = 1000 0000 | 0011 0000 | 0000 1100 | 0000 0010 = 1011 1110 ==> 1011 1110 00490 * See Even data row at the table below*/ 00491 00492 data_line_even[k] = ((temp_byte & 0x80) ? BLACK0 : WHITE0); // BLACK0 = 0x03 = 0000 0011 00493 data_line_even[k] |= ((temp_byte & 0x20) ? BLACK1 : WHITE1); // BLACK1 = 0x0C = 0000 1100 00494 data_line_even[k] |= ((temp_byte & 0x08) ? BLACK2 : WHITE2); // WHITE2 = 0x20 = 0010 0000 00495 data_line_even[k--] |= ((temp_byte & 0x02) ? BLACK3 : WHITE3); // WHITE3 = 0x80 = 1000 0000 00496 /* data_line_even[k] = 0000 0011 | 0000 1100 | 0010 0000 | 1000 0000 = 1010 1111 ==> 1111 1010 00497 * See Odd data row at the table below 00498 * +---------+----+----+----+----+----+----+----+----+ 00499 * | |bit7|bit6|bit5|bit4|bit3|bit2|bit1|bit0| 00500 * |temp_byte+----+----+----+----+----+----+----+----+ 00501 * | | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 00502 * +---------+----+----+----+----+----+----+----+----+ 00503 * | Color | W | B | W | W | B | W | B | B | W=White, B=Black, N=Nothing 00504 * +---------+----+----+----+----+----+----+----+----+ 00505 * | Stage 1 | B | W | B | B | W | B | W | W | Inverse 00506 * +---------+----+----+----+----+----+----+----+----+ 00507 * | Input | 11 | 10 | 11 | 11 | 10 | 11 | 10 | 10 | W=10, B=11, N=01 00508 * +---------+----+----+----+----+----+----+----+----+ 00509 * |Even data| 11 | | 11 | | 10 | | 10 | | = 1111 1010 00510 * +---------+----+----+----+----+----+----+----+----+ 00511 * |Odd data | | 10 | | 11 | | 11 | | 10 | = 1011 1110 00512 * +---------+----+----+----+----+----+----+----+----+ */ 00513 break; 00514 case Stage3: // New image 00515 data_line_odd[x] = ((temp_byte & 0x40) ? WHITE3 : BLACK3 ); 00516 data_line_odd[x] |= ((temp_byte & 0x10) ? WHITE2 : BLACK2 ); 00517 data_line_odd[x] |= ((temp_byte & 0x04) ? WHITE1 : BLACK1 ); 00518 data_line_odd[x] |= ((temp_byte & 0x01) ? WHITE0 : BLACK0 ); 00519 00520 data_line_even[k] = ((temp_byte & 0x80) ? WHITE0 : BLACK0 ); 00521 data_line_even[k] |= ((temp_byte & 0x20) ? WHITE1 : BLACK1 ); 00522 data_line_even[k] |= ((temp_byte & 0x08) ? WHITE2 : BLACK2 ); 00523 data_line_even[k--] |= ((temp_byte & 0x02) ? WHITE3 : BLACK3 ); 00524 break; 00525 } 00526 } 00527 } 00528 00529 00530 /** 00531 * \brief The base function to handle the driving stages for Frame and Block type 00532 * 00533 * \note 00534 * - There are 3 stages to complete an image update on COG_V230_G2 type EPD. 00535 * - For more details on the driving stages, please refer to the COG G2 document Section 5.4 00536 * 00537 * \param EPD_type_index The defined EPD size 00538 * \param image_ptr The pointer of image array that stores image that will send to COG 00539 * \param image_data_address The address of memory that stores image 00540 * \param stage_no The assigned stage number that will proceed 00541 * \param lineoffset Line data offset 00542 */ 00543 void stage_handle_Base(uint8_t EPD_type_index,uint8_t *image_prt,long image_data_address, 00544 uint8_t stage_no,uint8_t lineoffset) 00545 { 00546 struct EPD_V230_G2_Struct S_epd_v230; 00547 int16_t cycle,m,i; //m=number of steps 00548 //uint8_t isLastframe = 0; //If it is the last frame to send Nothing at the fist scan line 00549 uint8_t isLastBlock=0; //If the beginning line of block is in active range of EPD 00550 int16_t scanline_no=0; 00551 uint8_t *action_block_prt; 00552 long action_block_address; 00553 uint8_t byte_array[LINE_BUFFER_DATA_SIZE]; 00554 /** Stage 2: BLACK/WHITE image, Frame type */ 00555 if(stage_no==Stage2) 00556 { 00557 for(i=0;i<action__Waveform_param->stage2_cycle;i++) 00558 { 00559 same_data_frame (EPD_type_index,ALL_BLACK,action__Waveform_param->stage2_t1); 00560 same_data_frame (EPD_type_index,ALL_WHITE,action__Waveform_param->stage2_t2); 00561 } 00562 return; 00563 } 00564 /** Stage 1 & 3, Block type */ 00565 // The frame/block/step of Stage1 and Stage3 are default the same. 00566 stage_init(EPD_type_index, 00567 &S_epd_v230, 00568 action__Waveform_param->stage1_block1, 00569 action__Waveform_param->stage1_step1, 00570 action__Waveform_param->stage1_frame1); 00571 00572 /* Repeat number of frames */ 00573 for (cycle = 0; cycle < (S_epd_v230.frame_cycle ); cycle++) 00574 { 00575 00576 // if (cycle == (S_epd_v230.frame_cycle - 1)) isLastframe = 1; 00577 00578 isLastBlock = 0; 00579 S_epd_v230.step_y0 = 0; 00580 S_epd_v230.step_y1 = S_epd_v230.step_size ; 00581 S_epd_v230.block_y0 = 0; 00582 S_epd_v230.block_y1 = 0; 00583 /* Move number of steps */ 00584 for (m = 0; m < S_epd_v230.number_of_steps; m++) 00585 { 00586 S_epd_v230.block_y1 += S_epd_v230.step_size; 00587 S_epd_v230.block_y0 = S_epd_v230.block_y1 - S_epd_v230.block_size; 00588 /* reset block_y0=frame_y0 if block is not in active range of EPD */ 00589 if (S_epd_v230.block_y0 < S_epd_v230.frame_y0) S_epd_v230.block_y0 = S_epd_v230.frame_y0; 00590 00591 /* if the beginning line of block is in active range of EPD */ 00592 if (S_epd_v230.block_y1 == S_epd_v230.block_size) isLastBlock = 1; 00593 00594 if(image_prt!=NULL) 00595 { 00596 action_block_prt=(image_prt+(int)(S_epd_v230.block_y0*lineoffset)); 00597 } 00598 else if(_On_EPD_read_flash!=NULL) //Read line data in range of block, read first 00599 { 00600 action_block_address=image_data_address+(long)(S_epd_v230.block_y0*lineoffset); 00601 _On_EPD_read_flash(action_block_address,(uint8_t *)&byte_array, 00602 COG_parameters[EPD_type_index].horizontal_size); 00603 action_block_prt=(uint8_t *)&byte_array; 00604 } 00605 /* Update line data */ 00606 for (i = S_epd_v230.block_y0; i < S_epd_v230.block_y1; i++) 00607 { 00608 00609 if (i >= COG_parameters[EPD_type_index].vertical_size) break; 00610 //if (isLastframe && 00611 if ( 00612 isLastBlock &&(i < (S_epd_v230.step_size + S_epd_v230.block_y0))) 00613 { 00614 nothing_line(EPD_type_index); 00615 } 00616 else 00617 { 00618 read_line_data_handle(EPD_type_index,action_block_prt,stage_no); 00619 } 00620 00621 if(_On_EPD_read_flash!=NULL) //Read line data in range of block 00622 { 00623 action_block_address +=lineoffset; 00624 _On_EPD_read_flash(action_block_address,(uint8_t *)&byte_array, 00625 COG_parameters[EPD_type_index].horizontal_size); 00626 action_block_prt=(uint8_t *)&byte_array; 00627 } 00628 else action_block_prt+=lineoffset; 00629 00630 scanline_no= (COG_parameters[EPD_type_index].vertical_size-1)-i; 00631 00632 /* Scan byte shift per data line */ 00633 data_line_scan[(scanline_no>>2)] = SCAN_TABLE[(scanline_no%4)]; 00634 00635 /* the border uses the internal signal control byte. */ 00636 *data_line_border_byte=0x00; 00637 00638 /* Sending data */ 00639 epd_spi_send (0x0A, (uint8_t *)&COG_Line.uint8, 00640 COG_parameters[EPD_type_index].data_line_size); 00641 00642 00643 /* Turn on Output Enable */ 00644 epd_spi_send_byte (0x02, 0x07); 00645 00646 data_line_scan[(scanline_no>>2)]=0; 00647 00648 } 00649 } 00650 00651 } 00652 } 00653 00654 /** 00655 * \brief The driving stages from image array (image_data.h) to COG 00656 * 00657 * \param EPD_type_index The defined EPD size 00658 * \param image_ptr The pointer of image array that stores image that will send to COG 00659 * \param stage_no The assigned stage number that will proceed 00660 * \param lineoffset Line data offset 00661 */ 00662 void stage_handle(uint8_t EPD_type_index,uint8_t *image_prt,uint8_t stage_no,uint8_t lineoffset) 00663 { 00664 stage_handle_Base(EPD_type_index,image_prt,ADDRESS_NULL,stage_no,lineoffset); 00665 } 00666 00667 /** 00668 * \brief The driving stages from memory to COG 00669 * 00670 * \note 00671 * - This function is additional added here for developer if the image data 00672 * is stored in Flash memory. 00673 * 00674 * \param EPD_type_index The defined EPD size 00675 * \param image_data_address The address of flash memory that stores image 00676 * \param stage_no The assigned stage number that will proceed 00677 * \param lineoffset Line data offset 00678 */ 00679 static void stage_handle_ex(uint8_t EPD_type_index,long image_data_address,uint8_t stage_no,uint8_t lineoffset) { 00680 stage_handle_Base(EPD_type_index,NULL,image_data_address,stage_no,lineoffset); 00681 } 00682 00683 /** 00684 * \brief Write image data from memory array (image_data.h) to the EPD 00685 * 00686 * \param EPD_type_index The defined EPD size 00687 * \param previous_image_ptr The pointer of memory that stores previous image 00688 * \param new_image_ptr The pointer of memory that stores new image 00689 */ 00690 void EPD_display_from_array_prt (uint8_t EPD_type_index, uint8_t *previous_image_ptr, 00691 uint8_t *new_image_ptr) { 00692 _On_EPD_read_flash=0; 00693 stage_handle(EPD_type_index,new_image_ptr,Stage1,COG_parameters[EPD_type_index].horizontal_size); 00694 stage_handle(EPD_type_index,new_image_ptr,Stage2,COG_parameters[EPD_type_index].horizontal_size); 00695 stage_handle(EPD_type_index,new_image_ptr,Stage3,COG_parameters[EPD_type_index].horizontal_size); 00696 } 00697 00698 /** 00699 * \brief Write image data from Flash memory to the EPD 00700 * \note This function is additional added here for developer if the image data 00701 * is stored in Flash. 00702 * 00703 * \param EPD_type_index The defined EPD size 00704 * \param previous_image_flash_address The start address of memory that stores previous image 00705 * \param new_image_flash_address The start address of memory that stores new image 00706 * \param On_EPD_read_flash Developer needs to create an external function to read flash 00707 */ 00708 void EPD_display_from_flash_prt (uint8_t EPD_type_index, long previous_image_flash_address, 00709 long new_image_flash_address,EPD_read_flash_handler On_EPD_read_flash) { 00710 00711 uint8_t line_len; 00712 line_len=LINE_SIZE; 00713 if(line_len==0) line_len=COG_parameters[EPD_type_index].horizontal_size; 00714 00715 _On_EPD_read_flash=On_EPD_read_flash; 00716 stage_handle_ex(EPD_type_index,new_image_flash_address,Stage1,line_len); 00717 stage_handle_ex(EPD_type_index,new_image_flash_address,Stage2,line_len); 00718 stage_handle_ex(EPD_type_index,new_image_flash_address,Stage3,line_len); 00719 } 00720 00721 00722 /** 00723 * \brief Write Dummy Line to COG 00724 * \note A line whose all Scan Bytes are 0x00 00725 * 00726 * \param EPD_type_index The defined EPD size 00727 */ 00728 static inline void dummy_line(uint8_t EPD_type_index) { 00729 uint8_t i; 00730 for (i = 0; i < (COG_parameters[EPD_type_index].vertical_size/8); i++) { 00731 switch(EPD_type_index) { 00732 case EPD_144: 00733 COG_Line.line_data_by_size.line_data_for_144.scan[i]=0x00; 00734 break; 00735 case EPD_200: 00736 COG_Line.line_data_by_size.line_data_for_200.scan[i]=0x00; 00737 break; 00738 case EPD_270: 00739 COG_Line.line_data_by_size.line_data_for_270.scan[i]=0x00; 00740 break; 00741 } 00742 } 00743 /* Set charge pump voltage level reduce voltage shift */ 00744 epd_spi_send_byte (0x04, COG_parameters[EPD_type_index].voltage_level); 00745 00746 /* Sending data */ 00747 epd_spi_send (0x0A, (uint8_t *)&COG_Line.uint8, COG_parameters[EPD_type_index].data_line_size); 00748 00749 /* Turn on Output Enable */ 00750 epd_spi_send_byte (0x02, 0x07); 00751 } 00752 00753 00754 /** 00755 * \brief Write Border(Input) Dummy Line 00756 * \note Set Border byte 0xFF to write Black and set 0xAA to write White 00757 * 00758 * \param EPD_type_index The defined EPD size 00759 */ 00760 static void border_dummy_line(uint8_t EPD_type_index) 00761 { 00762 uint16_t i; 00763 for (i = 0; i < COG_parameters[EPD_type_index].data_line_size; i++) 00764 { 00765 COG_Line.uint8[i] = 0x00; 00766 } 00767 00768 *data_line_border_byte=BORDER_BYTE_B; 00769 //Write a Border(B) Dummy Line 00770 epd_spi_send (0x0a, (uint8_t *)&COG_Line.uint8, COG_parameters[EPD_type_index].data_line_size); 00771 //Turn on OE 00772 epd_spi_send_byte (0x02, 0x07); 00773 00774 sys_delay_ms(40); 00775 00776 *data_line_border_byte=BORDER_BYTE_W; 00777 //Write a Borde(B) Dummy Line 00778 epd_spi_send (0x0a, (uint8_t *)&COG_Line.uint8, COG_parameters[EPD_type_index].data_line_size); 00779 //Turn on OE 00780 epd_spi_send_byte (0x02, 0x07); 00781 00782 sys_delay_ms(200); 00783 00784 00785 } 00786 00787 00788 /** 00789 * \brief Power Off COG Driver 00790 * \note For detailed flow and description, please refer to the COG G2 document Section 6. 00791 * 00792 * \param EPD_type_index The defined EPD size 00793 */ 00794 uint8_t EPD_power_off(uint8_t EPD_type_index) { 00795 uint8_t y; 00796 00797 if(EPD_type_index==EPD_144 || EPD_type_index==EPD_200) { 00798 border_dummy_line(EPD_type_index); 00799 dummy_line(EPD_type_index); 00800 } 00801 00802 delay_ms (25); 00803 if(EPD_type_index==EPD_270) { 00804 EPD_border_low(); 00805 delay_ms (200); 00806 EPD_border_high(); 00807 } 00808 00809 //Check DC/DC 00810 if((SPI_R(0x0F,0x00) & 0x40) == 0x00) return ERROR_DC; 00811 00812 //Turn on Latch Reset 00813 epd_spi_send_byte (0x03, 0x01); 00814 //Turn off OE 00815 epd_spi_send_byte (0x02, 0x05); 00816 //Power off charge pump Vcom 00817 epd_spi_send_byte (0x05, 0x0E); 00818 //Power off charge pump neg voltage 00819 epd_spi_send_byte (0x05, 0x02); 00820 //Turn off all charge pump 00821 epd_spi_send_byte (0x05, 0x00); 00822 //Turn off OSC 00823 epd_spi_send_byte (0x07, 0x0D); 00824 00825 epd_spi_send_byte (0x04, 0x83); 00826 delay_ms(120); 00827 epd_spi_send_byte (0x04, 0x00); 00828 00829 epd_spi_detach (); 00830 EPD_cs_low(); 00831 EPD_rst_low(); 00832 EPD_Vcc_turn_off (); 00833 EPD_border_low(); 00834 delay_ms (10); 00835 00836 for(y=0;y<10;y++) 00837 { 00838 EPD_discharge_high (); 00839 delay_ms (10); 00840 EPD_discharge_low (); 00841 delay_ms (10); 00842 } 00843 return RES_OK; 00844 } 00845 00846 #endif 00847 00848 00849
Generated on Thu Jul 14 2022 17:10:35 by 1.7.2