diff --git a/lib/font.c b/lib/font.c index 481b927..1f93ebd 100644 --- a/lib/font.c +++ b/lib/font.c @@ -16,7 +16,7 @@ #include "font.h" /** @array Charset */ -const uint8_t FONTS[][5] PROGMEM = { +const uint8_t FONTS[][CHARS_COLS_LENGTH] PROGMEM = { { 0x00, 0x00, 0x00, 0x00, 0x00 }, // 20 space { 0x81, 0x81, 0x18, 0x81, 0x81 }, // 21 ! { 0x00, 0x07, 0x00, 0x07, 0x00 }, // 22 " diff --git a/lib/ssd1306.c b/lib/ssd1306.c index bd814a1..3eadf4a 100644 --- a/lib/ssd1306.c +++ b/lib/ssd1306.c @@ -9,12 +9,13 @@ * @datum 06.10.2020 * @update 19.07.2021 * @file ssd1306.c + * @version 2.0 * @tested AVR Atmega328 * * @depend font.h, twi.h * ---------------------------------------------------------------+ * @descr Version 1.0 -> applicable for 1 display - * Version 2.0 -> applicable for more than 1 display + * Version 2.0 -> rebuild to 'cacheMemLcd' array * ---------------------------------------------------------------+ * @usage Basic Setup for OLED Display */ @@ -159,10 +160,6 @@ static char cacheMemLcd[CACHE_SIZE_MEM]; // @var global - set area unsigned int set_area = (END_PAGE_ADDR - START_PAGE_ADDR + 1) * (END_COLUMN_ADDR - START_COLUMN_ADDR + 1); -// @var global - cache index column -unsigned short int indexCol = START_COLUMN_ADDR; -// @var global - cache index page -unsigned short int indexPage = START_PAGE_ADDR; /** * @desc SSD1306 Init @@ -274,7 +271,7 @@ uint8_t SSD1306_Send_StartAndSLAW (uint8_t address) /** * @desc SSD1306 Send command * - * @param uint8_t + * @param uint8_t command * * @return uint8_t */ @@ -306,7 +303,7 @@ uint8_t SSD1306_Send_Command (uint8_t command) } /** - * @desc SSD1306 Normal Colors + * @desc SSD1306 Normal colors * * @param uint8_t address * @@ -340,7 +337,7 @@ uint8_t SSD1306_NormalScreen (uint8_t address) } /** - * @desc SSD1306 Inverse Colors + * @desc SSD1306 Inverse colors * * @param uint8_t address * @@ -374,7 +371,7 @@ uint8_t SSD1306_InverseScreen (uint8_t address) } /** - * @desc SSD1306 Update Screen On + * @desc SSD1306 Update screen * * @param uint8_t address * @@ -429,294 +426,56 @@ uint8_t SSD1306_UpdateScreen (uint8_t address) /** * @desc SSD1306 Send Command * - * @param uint8_t address + * @param void * * @return void */ -void SSD1306_ClearScreen (uint8_t address) +void SSD1306_ClearScreen (void) { - // init status - uint8_t status = INIT_STATUS; - //short int i = 0; - // null cache memory lcd memset (cacheMemLcd, 0x00, CACHE_SIZE_MEM); -/* - // update - null col, increment page - status = SSD1306_SetPosition (address, 0, 0); - // request - if (SSD1306_SUCCESS != status) { - // error - return status; - } - - // TWI: start & SLAW - // ------------------------- - status = SSD1306_Send_StartAndSLAW (address); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - - // control byte data stream - // ------------------------- - status = TWI_MT_Send_Data (SSD1306_DATA_STREAM); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - - // erase whole area - // ------------------------- - while (i < set_area) { - // send null data - status = TWI_MT_Send_Data (0x00); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // increment - i++; - } - - // stop TWI - TWI_Stop (); -*/ - // success - return SSD1306_SUCCESS; } /** - * @desc SSD1306 Set Poisition + * @desc SSD1306 Set position * - * @param uint8_t address - * @param uint8_t - * @param uint8_t + * @param uint8_t column -> 0 ... 127 + * @param uint8_t page -> 0 ... 7 * - * @return uint8_t + * @return void */ -uint8_t SSD1306_SetPosition (uint8_t address, uint8_t x, uint8_t y) +void SSD1306_SetPosition (uint8_t x, uint8_t y) { - // variables - uint8_t status = INIT_STATUS; - - // TWI: start & SLAW - // ------------------------- - status = SSD1306_Send_StartAndSLAW (address); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - - // SET COLUMN address - // *************************************************** - // set column addr - // ------------------------- - status = SSD1306_Send_Command (SSD1306_SET_COLUMN_ADDR); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // start COLUMN - // ------------------------- - status = SSD1306_Send_Command (x); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // end COLUMN - // ------------------------- - status = SSD1306_Send_Command (END_COLUMN_ADDR); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // update column index - indexCol = x; - - // SET PAGE address - // *************************************************** - // set page addr - // ------------------------- - status = SSD1306_Send_Command (SSD1306_SET_PAGE_ADDR); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // start PAGE - // ------------------------- - status = SSD1306_Send_Command (y); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // end PAGE - // ------------------------- - status = SSD1306_Send_Command (END_PAGE_ADDR); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // update column index - indexPage = y; - - // stop TWI - TWI_Stop (); - - // success - return SSD1306_SUCCESS; + // counter + _counter = x + (y << 7); } /** * @desc SSD1306 Check Text Poisition * - * @param uint8_t address + * @param void * * @return uint8_t */ -uint8_t SSD1306_UpdTxtPosition (uint8_t address) +uint8_t SSD1306_UpdTxtPosition (void) { - // init status - uint8_t status = INIT_STATUS; // check end column position - unsigned short int x = indexCol + CHARS_COLS_LENGTH + 1; + uint8_t y = _counter >> 7; + uint8_t x = _counter - (y << 7); + uint8_t x_new = x + CHARS_COLS_LENGTH + 1; + // check position - if ((x > END_COLUMN_ADDR) && (indexPage > (END_PAGE_ADDR - 1))) { - // return out of range - return SSD1306_ERROR; - // if x out reach end but page in range - } else if ((x > END_COLUMN_ADDR) && (indexPage < END_PAGE_ADDR)) { - // update - column - indexCol = 0; - // update - page - indexPage = indexPage + 1; - // update - null col, increment page - status = SSD1306_SetPosition (address, indexCol, indexPage); - // request - if (SSD1306_SUCCESS != status) { - // error - return status; - } - } - // success - return SSD1306_SUCCESS; -} - -/** - * @desc Send 1 Byte of data - * - * @param uint8_t address - * @param uint8_t data - * - * @return void - */ -uint8_t SSD1306_SendByte (uint8_t address, uint8_t data) -{ - // init status - uint8_t status = INIT_STATUS; - - // TWI: start & SLAW - // ------------------------- - status = SSD1306_Send_StartAndSLAW (address); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - - // control byte data stream - // ------------------------- - status = TWI_MT_Send_Data (SSD1306_DATA_STREAM); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // send byte of data - // ------------------------- - status = TWI_MT_Send_Data (data); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - - // increment global index col - indexCol = indexCol + 1; - - // stop TWI - TWI_Stop (); - - // success - return SSD1306_SUCCESS; -} - -/** - * @desc Send same bytes - * - * @param uint8_t address - * @param uint8_t data - * @param uint8_t length - * - * @return void - */ -uint8_t SSD1306_SendSameBytes (uint8_t address, uint8_t data, uint8_t length) -{ - // index - unsigned short int i = 0; - // init status - uint8_t status = INIT_STATUS; - - // TWI: start & SLAW - // ------------------------- - status = SSD1306_Send_StartAndSLAW (address); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - - // control byte data stream - // ------------------------- - status = TWI_MT_Send_Data (SSD1306_DATA_STREAM); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // loop through data - while (i++ < length) { - // draw line only within 1 page - if (indexCol < MAX_X) { - // send byte of data - // ------------------------- - status = TWI_MT_Send_Data (data); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // increment global index col - indexCol = indexCol + 1; - } else { - // end loop - break; + if (x_new > END_COLUMN_ADDR) { + // if more than numbre of pages + if (y > END_PAGE_ADDR) { + // return out of range + return SSD1306_ERROR; + // if x out reach end but page in range + } else if (y < (END_PAGE_ADDR-1)) { + // update + _counter = ((++y) << 7); } } - - // stop TWI - TWI_Stop (); - // success return SSD1306_SUCCESS; } @@ -724,70 +483,29 @@ uint8_t SSD1306_SendSameBytes (uint8_t address, uint8_t data, uint8_t length) /** * @desc Draw character * - * @param uint8_t address * @param char character * * @return uint8_t */ -uint8_t SSD1306_DrawChar (uint8_t address, char character) +uint8_t SSD1306_DrawChar (char character) { // variables - uint8_t idxCol = 0; - // init status - uint8_t status = INIT_STATUS; + uint8_t i = 0; // update text position - if (SSD1306_UpdTxtPosition (address) != SSD1306_SUCCESS) { + if (SSD1306_UpdTxtPosition () == SSD1306_ERROR) { // error return SSD1306_ERROR; } - // TWI: start & SLAW - // ------------------------- - status = SSD1306_Send_StartAndSLAW (address); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - - // control byte data stream - // ------------------------- - status = TWI_MT_Send_Data (SSD1306_DATA_STREAM); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // loop through 5 bits - while (idxCol < CHARS_COLS_LENGTH) { - // send control byte data - // ------------------------- - status = TWI_MT_Send_Data (pgm_read_byte(&FONTS[character-32][idxCol])); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // increment - idxCol++; + while (i < CHARS_COLS_LENGTH) { + // read byte + cacheMemLcd[_counter++] = pgm_read_byte(&FONTS[character-32][i++]); } - // empty column - // ------------------------- - status = TWI_MT_Send_Data (CLEAR_COLOR); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - - // increment global index col - indexCol = indexCol + CHARS_COLS_LENGTH + 1; - - // stop TWI - TWI_Stop (); + // update position + _counter++; // success return SSD1306_SUCCESS; @@ -796,46 +514,31 @@ uint8_t SSD1306_DrawChar (uint8_t address, char character) /** * @desc SSD1306 Draw String * - * @param uint8_t address * @param char * string * * @return void */ -uint8_t SSD1306_DrawString (uint8_t address, char *str) +void SSD1306_DrawString (char *str) { - // init status - uint8_t status = INIT_STATUS; // init int i = 0; - // loop through character of string while (str[i] != '\0') { // draw string - status = SSD1306_DrawChar (address, str[i++]); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } + SSD1306_DrawChar (str[i++]); } - - // success - return SSD1306_SUCCESS; } /** * @desc Draw pixel * - * @param uint8_t - * @param uint8_t - * @param uint8_t + * @param uint8_t x -> 0 ... MAX_X + * @param uint8_t y -> 0 ... MAX_Y * - * @return void + * @return uint8_t */ -uint8_t SSD1306_DrawPixel (uint8_t address, uint8_t x, uint8_t y) +uint8_t SSD1306_DrawPixel (uint8_t x, uint8_t y) { - // variables - uint8_t status = INIT_STATUS; uint8_t page = 0; uint8_t pixel = 0; @@ -848,96 +551,10 @@ uint8_t SSD1306_DrawPixel (uint8_t address, uint8_t x, uint8_t y) page = y >> 3; // which pixel (y % 8) pixel = 1 << (y - (page << 3)); - - // TWI: start & SLAW - // ------------------------- - status = SSD1306_Send_StartAndSLAW (address); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - - // SET COLUMN address - // *************************************************** - // set column addr - // ------------------------- - status = SSD1306_Send_Command (SSD1306_SET_COLUMN_ADDR); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // start COLUMN - // ------------------------- - status = SSD1306_Send_Command (x); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // end COLUMN - // ------------------------- - status = SSD1306_Send_Command (END_COLUMN_ADDR); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // update column index - indexCol = x; - - // SET PAGE address - // *************************************************** - // set page addr - // ------------------------- - status = SSD1306_Send_Command (SSD1306_SET_PAGE_ADDR); - // request - start TWI - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // start PAGE - // ------------------------- - status = SSD1306_Send_Command (page); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // end PAGE - // ------------------------- - status = SSD1306_Send_Command (END_PAGE_ADDR); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // update column index - indexPage = y; - - // ------------------------------------------------------ - // control byte data stream - status = TWI_MT_Send_Data (SSD1306_DATA_STREAM); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - // send byte of data - status = TWI_MT_Send_Data (pixel); - // request success - if (SSD1306_SUCCESS != status) { - // error - return status; - } - - // increment global index col - indexCol = indexCol + 1; - // ------------------------------------------------------ - - // stop TWI - TWI_Stop (); + // update counter + _counter = x + (page << 7); + // save pixel + cacheMemLcd[_counter++] |= pixel; // success return SSD1306_SUCCESS; @@ -947,7 +564,6 @@ uint8_t SSD1306_DrawPixel (uint8_t address, uint8_t x, uint8_t y) * @desc Draw line by Bresenham algoritm * @surce https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm * - * @param uint8_t address * @param uint8_t x start position / 0 <= cols <= MAX_X-1 * @param uint8_t x end position / 0 <= cols <= MAX_X-1 * @param uint8_t y start position / 0 <= rows <= MAX_Y-1 @@ -955,7 +571,7 @@ uint8_t SSD1306_DrawPixel (uint8_t address, uint8_t x, uint8_t y) * * @return uint8_t */ -uint8_t SSD1306_DrawLine (uint8_t address, uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2) +uint8_t SSD1306_DrawLine (uint8_t x1, uint8_t x2, uint8_t y1, uint8_t y2) { // determinant int16_t D; @@ -990,7 +606,7 @@ uint8_t SSD1306_DrawLine (uint8_t address, uint8_t x1, uint8_t x2, uint8_t y1, u // calculate determinant D = (delta_y << 1) - delta_x; // draw first pixel - SSD1306_DrawPixel (address, x1, y1); + SSD1306_DrawPixel (x1, y1); // check if x1 equal x2 while (x1 != x2) { // update x1 @@ -1005,14 +621,14 @@ uint8_t SSD1306_DrawLine (uint8_t address, uint8_t x1, uint8_t x2, uint8_t y1, u // update deteminant D += 2*delta_y; // draw next pixel - SSD1306_DrawPixel (address, x1, y1); + SSD1306_DrawPixel (x1, y1); } // for m > 1 (dy > dx) } else { // calculate determinant D = delta_y - (delta_x << 1); // draw first pixel - SSD1306_DrawPixel (address, x1, y1); + SSD1306_DrawPixel (x1, y1); // check if y2 equal y1 while (y1 != y2) { // update y1 @@ -1027,44 +643,9 @@ uint8_t SSD1306_DrawLine (uint8_t address, uint8_t x1, uint8_t x2, uint8_t y1, u // update deteminant D -= 2*delta_x; // draw next pixel - SSD1306_DrawPixel (address, x1, y1); + SSD1306_DrawPixel (x1, y1); } } // success return return SSD1306_SUCCESS; } - -/** - * @desc Draw horizontal line - * - * @param uint8_t address - * @param uint8_t - * @param uint8_t - * @param uint8_t - * - * @return void - */ -uint8_t SSD1306_DrawLineHorizontal (uint8_t address, uint8_t x, uint8_t y, uint8_t len) -{ - uint8_t page = 0; - uint8_t pixel = 0; - - // if out of range - if ((x > MAX_X) && (y > MAX_Y)) { - // out of range - return SSD1306_ERROR; - } - // find page (y / 8) - page = y >> 3; - // which pixel (y % 8) - pixel |= 1 << (y - (page << 3)); - - // send position - SSD1306_SetPosition (address, x, page); - // draw pixel - SSD1306_SendSameBytes (address, pixel, len); - - // success - return SSD1306_SUCCESS; -} - diff --git a/lib/ssd1306.h b/lib/ssd1306.h index 58dfb5c..b99bd72 100644 --- a/lib/ssd1306.h +++ b/lib/ssd1306.h @@ -9,12 +9,13 @@ * @datum 06.10.2020 * @update 19.07.2021 * @file ssd1306.h + * @version 2.0 * @tested AVR Atmega328 * * @depend font.h, twi.h * ---------------------------------------------------------------+ * @descr Version 1.0 -> applicable for 1 display - * Version 2.0 -> applicable for more than 1 display + * Version 2.0 -> rebuild to 'cacheMemLcd' array * ---------------------------------------------------------------+ * @usage Basic Setup for OLED Display */ @@ -86,12 +87,11 @@ #define MAX_X END_COLUMN_ADDR #define MAX_Y (END_PAGE_ADDR+1)*8 + + // @var set area + unsigned int _counter; // @var set area unsigned int set_area; - // @var cache index column - unsigned short int indexCol; - // @var cache index page - unsigned short int indexPage; /** * @desc SSD1306 Init - set frequency @@ -123,11 +123,11 @@ /** * @desc SSD1306 Clear Screen * - * @param uint8_t + * @param void * - * @return uint8_t + * @return void */ - uint8_t SSD1306_ClearScreen (uint8_t); + void SSD1306_ClearScreen (void); /** * @desc SSD1306 Normal Colors @@ -148,47 +148,44 @@ uint8_t SSD1306_InverseScreen (uint8_t); /** - * @desc SSD1306 Check Text Position + * @desc SSD1306 Update text position * - * @param uint8_t + * @param void * * @return uint8_t */ - uint8_t SSD1306_UpdTxtPosition (uint8_t); + uint8_t SSD1306_UpdTxtPosition (void); /** - * @desc SSD1306 Set Position + * @desc SSD1306 Set position * * @param uint8_t * @param uint8_t - * @param uint8_t * - * @return char + * @return void */ - uint8_t SSD1306_SetPosition (uint8_t, uint8_t, uint8_t); + void SSD1306_SetPosition (uint8_t, uint8_t); /** - * @desc SSD1306 Draw Character + * @desc SSD1306 Draw character * - * @param uint8_t * @param char * * @return uint8_t */ - uint8_t SSD1306_DrawChar (uint8_t, char); + uint8_t SSD1306_DrawChar (char); /** - * @desc SSD1306 Draw String + * @desc SSD1306 Draw string * - * @param uint8_t * @param char * * - * @return uint8_t + * @return void */ - uint8_t SSD1306_DrawString (uint8_t, char *); + void SSD1306_DrawString (char *); /** - * @desc SSD1306 Update Screen On + * @desc SSD1306 Update screen * * @param uint8_t * @@ -210,11 +207,10 @@ * * @param uint8_t * @param uint8_t - * @param uint8_t * - * @return void + * @return uint8_t */ - uint8_t SSD1306_DrawPixel (uint8_t, uint8_t, uint8_t); + uint8_t SSD1306_DrawPixel (uint8_t, uint8_t); /** * @desc Draw line @@ -223,43 +219,9 @@ * @param uint8_t * @param uint8_t * @param uint8_t - * @param uint8_t * * @return uint8_t */ - uint8_t SSD1306_DrawLine (uint8_t, uint8_t, uint8_t, uint8_t, uint8_t); - - /** - * @desc SSD1306 Draw line horizontal - * - * @param uint8_t - * @param uint8_t - * @param uint8_t - * @param uint8_t - * - * @return void - */ - uint8_t SSD1306_DrawLineHorizontal (uint8_t, uint8_t, uint8_t, uint8_t); - - /** - * @desc SSD1306 Send byte - * - * @param uint8_t - * @param uint8_t - * - * @return void - */ - uint8_t SSD1306_SendByte (uint8_t, uint8_t); - - /** - * @desc SSD1306 Send same bytes - * - * @param uint8_t - * @param uint8_t - * @param uint8_t - * - * @return uint8_t - */ - uint8_t SSD1306_SendSameBytes (uint8_t, uint8_t, uint8_t); + uint8_t SSD1306_DrawLine (uint8_t, uint8_t, uint8_t, uint8_t); #endif diff --git a/main.c b/main.c index b99e3d1..ba54c9d 100644 --- a/main.c +++ b/main.c @@ -14,7 +14,7 @@ * @depend ssd1306.h * ---------------------------------------------------------------+ * @descr Version 1.0 -> applicable for 1 display - * Version 2.0 -> applicable for more than 1 display + * Version 2.0 -> rebuild to 'cacheMemLcd' array * ---------------------------------------------------------------+ */ @@ -37,29 +37,27 @@ int main(void) SSD1306_Init (addr); // clear screen - SSD1306_ClearScreen (addr); + SSD1306_ClearScreen (); + // clear screen + SSD1306_ClearScreen (); // draw line - //SSD1306_DrawLineHorizontal (addr, 4, 4, 115); - // set position x, y - //SSD1306_SetPosition (addr, 1, 1); - - //for (char i = 1; i < MAX_Y; i++) { - SSD1306_DrawPixel (addr, 0, 0); - SSD1306_DrawPixel (addr, 0, 1); - SSD1306_DrawPixel (addr, 0, 2); - SSD1306_DrawPixel (addr, 1, 1); - SSD1306_DrawPixel (addr, 2, 2); - SSD1306_DrawPixel (addr, 3, 3); - SSD1306_DrawPixel (addr, 4, 4); - //SSD1306_DrawLine (addr, 0, MAX_X-1, MAX_Y-1, MAX_Y-1); - //} - + SSD1306_DrawLine (0, MAX_X, 4, 4); + // set position + SSD1306_SetPosition (7, 1); // draw string - //SSD1306_DrawString (addr, "SSD1306 OLED DRIVER"); + SSD1306_DrawString ("SSD1306 OLED DRIVER"); // draw line - //SSD1306_DrawLineHorizontal (addr, 4, 18, 115); + SSD1306_DrawLine (0, MAX_X, 18, 18); + // set position + SSD1306_SetPosition (40, 3); + // draw string + SSD1306_DrawString ("MATIASUS"); + // set position + SSD1306_SetPosition (53, 5); + // draw string + SSD1306_DrawString ("2021"); // update - //SSD1306_UpdateScreen (addr); + SSD1306_UpdateScreen (addr); // return value return 0; diff --git a/main.hex b/main.hex index f117127..882e9bc 100644 --- a/main.hex +++ b/main.hex @@ -38,10 +38,10 @@ :10025000000221007F02220007004001D30000A11C :1002600000C801DA1201817F00A400A601D5800137 :10027000D9C201DB20018D1400AF11241FBECFEFC6 -:10028000D8E0DEBFCDBF11E0A0E0B1E0E6EEF8E0DF -:1002900002C005900D92A230B107D9F725E0A2E087 -:1002A000B1E001C01D92A630B207E1F70E944504FB -:1002B0000C9471040C94000083E08093B800E9EB87 +:10028000D8E0DEBFCDBF11E0A0E0B1E0EAEEF6E0DD +:1002900002C005900D92A432B107D9F725E0A4E27F +:1002A000B1E001C01D92A632B207E1F70E944203FD +:1002B0000C9473030C94000083E08093B800E9EB86 :1002C000F0E08081908182708160892B8083089525 :1002D0008091B90087758093B90084EA8093BC004F :1002E0008091BC0087FFFCCF8091B900887F883067 @@ -68,78 +68,48 @@ :10043000811103C086EA0C94D40108950E94C8017A :10044000811103C087EA0C94D4010895CF93DF9300 :100450000E94C801811113C080E40E94990181119A -:100460000EC0C6E0D1E089910E949901811107C0B8 -:1004700085E0C630D807B9F70E94C40180E0DF915B -:10048000CF91089580E094E0E6E0F1E0DF019C0187 -:100490001D9221503040E1F780E00895CF93DF9323 -:1004A000D62FC42F0E94C80181112DC081E20E9465 -:1004B000D401811128C08D2F0E94D401811123C045 -:1004C0008FE70E94D40181111EC06D2F70E07093E0 -:1004D00005016093040182E20E94D401811113C0DE -:1004E0008C2F0E94D40181110EC087E00E94D4019C -:1004F000811109C04C2F50E0509303014093020139 -:100500000E94C40180E0DF91CF9108952091040101 -:10051000309105012A5F3F4F20383105A0F040910E -:100520000201509103014730510578F41092050102 -:10053000109204014F5F5F4F5093030140930201FB -:1005400060E00C944E0280E0089581E00895CF931E -:10055000C62F0E94C801811116C080E40E94990133 -:10056000811111C08C2F0E94990181110CC08091C2 -:100570000401909105010196909305018093040177 -:100580000E94C40180E0CF910895FF920F931F93C2 -:10059000CF93DF93F62EC42F0E94C801811126C08D -:1005A00080E40E949901811121C000E010E0D0E0B8 -:1005B0000C171D07C0F480910401909105018F373D -:1005C000910588F48F2D0E9499010F5F1F4F8111B3 -:1005D0000DC0809104019091050101969093050151 -:1005E00080930401E5CF0E94C40180E0DF91CF91A8 -:1005F0001F910F91FF9008950F931F93CF93DF9357 -:10060000D82FC62F0E948602811132C08D2F0E94E2 -:10061000C80181112EC080E40E949901811129C076 -:1006200085E0C802E001112400E010E0C05AD109C1 -:10063000FE01E00FF11FE859FF4F84910E949901DC -:10064000811117C00F5F1F4F0530110589F70E94F8 -:10065000990181110EC080910401909105010696C7 -:1006600090930501809304010E94C40180E001C0C1 -:1006700081E0DF91CF911F910F9108951F93CF9348 -:10068000DF93182FEB016991662331F0812F0E94CF -:10069000FC028823C1F301C080E0DF91CF911F915C -:1006A00008951F93CF93DF9367FF03C0413408F091 -:1006B00053C0C42FD62F0E94C80181114EC081E2C1 -:1006C0000E94D401811149C08D2F0E94D401811153 -:1006D00044C08FE70E94D40181113FC06D2F70E0AC -:1006E000709305016093040182E20E94D40181119C -:1006F00034C01C2F169516951695812F0E94D40193 -:1007000081112BC087E00E94D401811126C0D0E066 -:10071000D0930301C093020180E40E9499018111EA -:100720001CC088E0189FC019D109112481E001C0C4 -:10073000880FCA95EAF70E94990181110EC0809135 -:1007400004019091050101969093050180930401A5 -:100750000E94C40180E001C081E0DF91CF911F9130 -:1007600008957F928F929F92AF92BF92CF92DF9225 -:10077000EF92FF920F931F93CF93DF93E82EF62E05 -:10078000742E122F802E242F30E0261B3109802F4B -:1007900090E0811B910937FF05C031952195310902 -:1007A0000FEF01C001E097FF06C091958195910977 -:1007B00099249A9402C0992493946C01CC0CDD1C6A -:1007C0005901AA0CBB1C821793079CF4E601C21BBB -:1007D000D30B412F6F2D8E2D0E945103F714D9F0AA -:1007E000F00ED7FD03C0190DCA19DB09CC0DDD1DB4 -:1007F000F0CFEC01CA19DB09412F6F2D8E2D0E941D -:100800005103181541F0190D1C161D069CF3F00E2E -:10081000CC0DDD1DEFCF80E0DF91CF911F910F91C7 -:10082000FF90EF90DF90CF90BF90AF909F908F9010 -:100830007F9008950F931F93CF93DF9367FF02C0BC -:100840004134E8F4122FC42FD82F042F06950695B3 -:100850000695402F0E944E024C2F50E088E0089FE2 -:1008600040195109112461E070E001C0660F4A95FA -:10087000EAF7412F8D2F0E94C50280E001C081E080 -:10088000DF91CF911F910F9108958CE30E94E101B8 -:100890008CE30E94420240E060E08CE30E9451033E -:1008A00041E060E08CE30E94510342E060E08CE3B1 -:1008B0000E94510341E061E08CE30E94510342E059 -:1008C00062E08CE30E94510343E063E08CE30E940A -:1008D000510344E064E08CE30E94510380E090E027 -:0608E0000895F894FFCF1B -:0208E60000040C +:100460000EC0C4E2D1E089910E949901811107C0B8 +:1004700085E0C432D807B9F70E94C40180E0DF915B +:10048000CF91089580E094E0E4E2F1E0DF019C0187 +:100490001D9221503040E1F7089590E020E8629FDE +:1004A000800D911D112490932505809324050895B6 +:1004B0002091240530912505C901880F892F881FB7 +:1004C000990B91952A5F482F479544274795241B00 +:1004D00027FF10C0883060F4863060F48F5F20E81A +:1004E000829FC0011124909325058093240502C0AA +:1004F00081E0089580E00895CF93C82F0E945802AC +:10050000813011F12091240530912505D901AC5D90 +:10051000BE4F45E0C402C001112440E050E0805AC3 +:100520009109FC01E40FF51FE859FF4FE491ED93A9 +:100530004F5F5F4F45305105A1F72A5F3F4F309322 +:1005400025052093240580E0CF910895CF93DF9374 +:10055000EC018991882319F00E947C02FACFDF9187 +:10056000CF91089587FF02C0613420F5262F26958C +:100570002695269530E0F901F695FE2FEE27F795A2 +:10058000E795E80FF11DCF01019690932505809323 +:100590002405EC5DFE4F88E0289F6019112481E05E +:1005A00090E001C0880F6A95EAF79081892B8083DB +:1005B00080E0089581E008958F929F92AF92BF925C +:1005C000CF92DF92EF92FF920F931F93CF93DF931F +:1005D000082FA62E142FB22E262F30E0281B31090B +:1005E0008B2D90E0841B910937FF06C03195219532 +:1005F000310999249A9402C09924939497FF06C0D4 +:1006000091958195910988248A9402C088248394C5 +:100610007C01EE0CFF1C6901CC0CDD1C82179307DA +:1006200094F4E701C21BD30B612F802F0E94B2020A +:100630000A15D1F0090DD7FD03C0180DCC19DD093D +:10064000CE0DDF1DF1CFEC01CC19DD09612F802F1C +:100650000E94B2021B1541F0180D1C161D06A4F3D2 +:10066000090DCE0DDF1DF0CF80E0DF91CF911F91FE +:100670000F91FF90EF90DF90CF90BF90AF909F9041 +:100680008F9008958CE30E94E1010E9442020E9433 +:10069000420224E044E06FE780E00E94DC0261E077 +:1006A00087E00E944D0282E091E00E94A60222E1D2 +:1006B00042E16FE780E00E94DC0263E088E20E9492 +:1006C0004D0286E191E00E94A60265E085E30E946A +:1006D0004D028FE191E00E94A6028CE30E94260267 +:0A06E00080E090E00895F894FFCF49 +:1006EA00000453534431333036204F4C45442044A0 +:1006FA005249564552004D415449415355530032CF +:04070A003032310058 :00000001FF