Advertisement
Guest User

Untitled

a guest
Dec 28th, 2022
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 58.58 KB | None | 0 0
  1. /*
  2.  * Sava @ 2022
  3.  * JBC Soldering Station Contrloler / PIC12F1840
  4.  * This is a free software with NO WARRANTY
  5.  */
  6.  
  7. // CONFIG1
  8. #pragma config FOSC = INTOSC    // Oscillator Selection->INTOSC oscillator: I/O function on CLKIN pin
  9. #pragma config WDTE = OFF    // Watchdog Timer Enable->WDT disabled
  10. #pragma config PWRTE = OFF    // Power-up Timer Enable->PWRT disabled
  11. #pragma config MCLRE = OFF    // MCLR Pin Function Select->MCLR/VPP pin function is digital input
  12. #pragma config CP = ON    // Flash Program Memory Code Protection->Program memory code protection is enabled
  13. #pragma config CPD = ON    // Data Memory Code Protection->Data memory code protection is enabled
  14. #pragma config BOREN = ON    // Brown-out Reset Enable->Brown-out Reset enabled
  15. #pragma config CLKOUTEN = OFF    // Clock Out Enable->CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
  16. #pragma config IESO = ON    // Internal/External Switchover->Internal/External Switchover mode is enabled
  17. #pragma config FCMEN = ON    // Fail-Safe Clock Monitor Enable->Fail-Safe Clock Monitor is enabled
  18.  
  19. // CONFIG2
  20. #pragma config WRT = OFF    // Flash Memory Self-Write Protection->Write protection off
  21. #pragma config PLLEN = OFF    // PLL Enable->4x PLL disabled
  22. #pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable->Stack Overflow or Underflow will cause a Reset
  23. #pragma config BORV = LO    // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (Vbor), low trip point selected.
  24. #pragma config LVP = OFF    // Low-Voltage Programming Enable->High-voltage on MCLR/VPP must be used for programming
  25.  
  26. #include <xc.h>
  27. #include <stdio.h>
  28. #include <stdint.h>
  29. #include <stdbool.h>
  30. #include <stdio.h>
  31.  
  32. #pragma warning disable 520
  33.  
  34. #define _XTAL_FREQ 32000000
  35.  
  36. #define ENABLE_UART_DEBUG 0
  37.  
  38. #define INPUT   1
  39. #define OUTPUT  0
  40.  
  41. #define HIGH    1
  42. #define LOW     0
  43.  
  44. #define ANALOG      1
  45. #define DIGITAL     0
  46.  
  47. #define PULL_UP_ENABLED      1
  48. #define PULL_UP_DISABLED     0
  49.  
  50. // get/set IO_RA0 aliases
  51. #define IO_RA0_TRIS                 TRISAbits.TRISA0
  52. #define IO_RA0_LAT                  LATAbits.LATA0
  53. #define IO_RA0_PORT                 PORTAbits.RA0
  54. #define IO_RA0_WPU                  WPUAbits.WPUA0
  55. #define IO_RA0_ANS                  ANSELAbits.ANSA0
  56. #define IO_RA0_SetHigh()            do { LATAbits.LATA0 = 1; } while(0)
  57. #define IO_RA0_SetLow()             do { LATAbits.LATA0 = 0; } while(0)
  58. #define IO_RA0_Toggle()             do { LATAbits.LATA0 = ~LATAbits.LATA0; } while(0)
  59. #define IO_RA0_GetValue()           PORTAbits.RA0
  60. #define IO_RA0_SetDigitalInput()    do { TRISAbits.TRISA0 = 1; } while(0)
  61. #define IO_RA0_SetDigitalOutput()   do { TRISAbits.TRISA0 = 0; } while(0)
  62. #define IO_RA0_SetPullup()          do { WPUAbits.WPUA0 = 1; } while(0)
  63. #define IO_RA0_ResetPullup()        do { WPUAbits.WPUA0 = 0; } while(0)
  64. #define IO_RA0_SetAnalogMode()      do { ANSELAbits.ANSA0 = 1; } while(0)
  65. #define IO_RA0_SetDigitalMode()     do { ANSELAbits.ANSA0 = 0; } while(0)
  66.  
  67. // get/set SCL aliases
  68. #define SCL_TRIS                 TRISAbits.TRISA1
  69. #define SCL_LAT                  LATAbits.LATA1
  70. #define SCL_PORT                 PORTAbits.RA1
  71. #define SCL_WPU                  WPUAbits.WPUA1
  72. #define SCL_ANS                  ANSELAbits.ANSA1
  73. #define SCL_SetHigh()            do { LATAbits.LATA1 = 1; } while(0)
  74. #define SCL_SetLow()             do { LATAbits.LATA1 = 0; } while(0)
  75. #define SCL_Toggle()             do { LATAbits.LATA1 = ~LATAbits.LATA1; } while(0)
  76. #define SCL_GetValue()           PORTAbits.RA1
  77. #define SCL_SetDigitalInput()    do { TRISAbits.TRISA1 = 1; } while(0)
  78. #define SCL_SetDigitalOutput()   do { TRISAbits.TRISA1 = 0; } while(0)
  79. #define SCL_SetPullup()          do { WPUAbits.WPUA1 = 1; } while(0)
  80. #define SCL_ResetPullup()        do { WPUAbits.WPUA1 = 0; } while(0)
  81. #define SCL_SetAnalogMode()      do { ANSELAbits.ANSA1 = 1; } while(0)
  82. #define SCL_SetDigitalMode()     do { ANSELAbits.ANSA1 = 0; } while(0)
  83.  
  84. // get/set SDA aliases
  85. #define SDA_TRIS                 TRISAbits.TRISA2
  86. #define SDA_LAT                  LATAbits.LATA2
  87. #define SDA_PORT                 PORTAbits.RA2
  88. #define SDA_WPU                  WPUAbits.WPUA2
  89. #define SDA_ANS                  ANSELAbits.ANSA2
  90. #define SDA_SetHigh()            do { LATAbits.LATA2 = 1; } while(0)
  91. #define SDA_SetLow()             do { LATAbits.LATA2 = 0; } while(0)
  92. #define SDA_Toggle()             do { LATAbits.LATA2 = ~LATAbits.LATA2; } while(0)
  93. #define SDA_GetValue()           PORTAbits.RA2
  94. #define SDA_SetDigitalInput()    do { TRISAbits.TRISA2 = 1; } while(0)
  95. #define SDA_SetDigitalOutput()   do { TRISAbits.TRISA2 = 0; } while(0)
  96. #define SDA_SetPullup()          do { WPUAbits.WPUA2 = 1; } while(0)
  97. #define SDA_ResetPullup()        do { WPUAbits.WPUA2 = 0; } while(0)
  98. #define SDA_SetAnalogMode()      do { ANSELAbits.ANSA2 = 1; } while(0)
  99. #define SDA_SetDigitalMode()     do { ANSELAbits.ANSA2 = 0; } while(0)
  100.  
  101. // get/set IO_RA3 aliases
  102. #define IO_RA3_TRIS                 TRISAbits.TRISA3
  103. #define IO_RA3_PORT                 PORTAbits.RA3
  104. #define IO_RA3_WPU                  WPUAbits.WPUA3
  105. #define IO_RA3_GetValue()           PORTAbits.RA3
  106. #define IO_RA3_SetDigitalInput()    do { TRISAbits.TRISA3 = 1; } while(0)
  107. #define IO_RA3_SetDigitalOutput()   do { TRISAbits.TRISA3 = 0; } while(0)
  108. #define IO_RA3_SetPullup()          do { WPUAbits.WPUA3 = 1; } while(0)
  109. #define IO_RA3_ResetPullup()        do { WPUAbits.WPUA3 = 0; } while(0)
  110.  
  111. // get/set IO_RA4 aliases
  112. #define IO_RA4_TRIS                 TRISAbits.TRISA4
  113. #define IO_RA4_LAT                  LATAbits.LATA4
  114. #define IO_RA4_PORT                 PORTAbits.RA4
  115. #define IO_RA4_WPU                  WPUAbits.WPUA4
  116. #define IO_RA4_ANS                  ANSELAbits.ANSA4
  117. #define IO_RA4_SetHigh()            do { LATAbits.LATA4 = 1; } while(0)
  118. #define IO_RA4_SetLow()             do { LATAbits.LATA4 = 0; } while(0)
  119. #define IO_RA4_Toggle()             do { LATAbits.LATA4 = ~LATAbits.LATA4; } while(0)
  120. #define IO_RA4_GetValue()           PORTAbits.RA4
  121. #define IO_RA4_SetDigitalInput()    do { TRISAbits.TRISA4 = 1; } while(0)
  122. #define IO_RA4_SetDigitalOutput()   do { TRISAbits.TRISA4 = 0; } while(0)
  123. #define IO_RA4_SetPullup()          do { WPUAbits.WPUA4 = 1; } while(0)
  124. #define IO_RA4_ResetPullup()        do { WPUAbits.WPUA4 = 0; } while(0)
  125. #define IO_RA4_SetAnalogMode()      do { ANSELAbits.ANSA4 = 1; } while(0)
  126. #define IO_RA4_SetDigitalMode()     do { ANSELAbits.ANSA4 = 0; } while(0)
  127.  
  128. // get/set IO_RA5 aliases
  129. #define IO_RA5_TRIS                 TRISAbits.TRISA5
  130. #define IO_RA5_LAT                  LATAbits.LATA5
  131. #define IO_RA5_PORT                 PORTAbits.RA5
  132. #define IO_RA5_WPU                  WPUAbits.WPUA5
  133. #define IO_RA5_SetHigh()            do { LATAbits.LATA5 = 1; } while(0)
  134. #define IO_RA5_SetLow()             do { LATAbits.LATA5 = 0; } while(0)
  135. #define IO_RA5_Toggle()             do { LATAbits.LATA5 = ~LATAbits.LATA5; } while(0)
  136. #define IO_RA5_GetValue()           PORTAbits.RA5
  137. #define IO_RA5_SetDigitalInput()    do { TRISAbits.TRISA5 = 1; } while(0)
  138. #define IO_RA5_SetDigitalOutput()   do { TRISAbits.TRISA5 = 0; } while(0)
  139. #define IO_RA5_SetPullup()          do { WPUAbits.WPUA5 = 1; } while(0)
  140. #define IO_RA5_ResetPullup()        do { WPUAbits.WPUA5 = 0; } while(0)
  141.  
  142. typedef void (*interruptHandler)(void);
  143. void (*i2c_driver_busCollisionISR)(void);
  144. void (*i2c_driver_i2cISR)(void);
  145.  
  146. inline void i2c_driver_close(void)
  147. {
  148.     SSP1CON1bits.SSPEN = 0;
  149. }
  150.  
  151. /* Interrupt Control */
  152. inline void mssp_enableIRQ(void)
  153. {
  154.     PIE1bits.SSP1IE = 1;
  155. }
  156.  
  157. inline __bit mssp_IRQisEnabled(void)
  158. {
  159.     return PIE1bits.SSP1IE;
  160. }
  161.  
  162. inline void mssp_disableIRQ(void)
  163. {
  164.     PIE1bits.SSP1IE = 0;
  165. }
  166.  
  167. inline void mssp_clearIRQ(void)
  168. {
  169.     PIR1bits.SSP1IF = 0;
  170. }
  171.  
  172. inline __bit mssp_IRQisSet(void)
  173. {
  174.     return PIR1bits.SSP1IF;
  175. }
  176.  
  177. inline void mssp_waitForEvent(uint16_t timeout)
  178. {
  179.     uint16_t to = timeout;
  180.  
  181.     if (PIR1bits.SSP1IF == 0)
  182.     {
  183.         while(to--)
  184.         {
  185.             if (PIR1bits.SSP1IF) break;
  186.             __delay_us(100);
  187.         }
  188.     }
  189. }
  190.  
  191. __bit i2c_driver_open(void)
  192. {
  193.     if (!SSP1CON1bits.SSPEN)
  194.     {
  195.         SSP1STAT = 0x00;
  196.         SSP1CON1 = 0x28;
  197.         SSP1CON2 = 0x00;
  198.         SSP1ADD = 0x13;
  199.         return true;
  200.     }
  201.     else
  202.         return false;
  203. }
  204.  
  205. __bit i2c_driver_initSlaveHardware(void)
  206. {
  207.     if(!SSP1CON1bits.SSPEN)
  208.     {
  209. /* NOTE on AHEN:
  210.  * If multiple slaves are to be emulated, then AHEN must be set.  It must be set
  211.  * because the driver needs to selectively ACK/NACK the address depending on its
  212.  * ability to handle the address.
  213. */
  214.  
  215. /* NOTE on DHEN:
  216.  * DHEN must be set so that the data is not automatically NACK'ed if it is not read
  217.  * from the SSPBUF.  This driver will ALWAYS read the SSPBUF so that it can pass
  218.  * the value to the appropriate slave handler.  Because the data is ALWAYS read
  219.  * the data will always be ACK'd if DHEN is cleared.  If the slave does not want
  220.  * the data byte from the master then it will return false and a NACK will be returned.
  221.  */
  222.  
  223. /* NOTE on SEN:
  224.  * SEN will be set enabling clock stretching.  This is because we don't know how
  225.  * long the user will take to process data bytes in their callbacks.  If they are fast,
  226.  * we may not need to stretch the clock.  If they are slow, we need to stretch the clock.
  227.  * If we ALWAYS stretch the clock, we will release the clock when the ISR is complete.
  228.  */
  229.  
  230. /* NOTE on PCIE:
  231.  * PCIE will be set to enable interrupts on STOP.  This will allow us know when
  232.  * the master is finished
  233.  */
  234.        
  235. /* NOTE on SCIE:
  236.  * SCIE will be set to enable interrupts on START.  This will allow us to detect
  237.  * both a START and a RESTART event and prepare to restart communications.
  238.  */
  239.         SSP1CON1 |= 0x06; //setup I2C Slave (7-bit Addressing)
  240.         SSP1STAT = 0x00;
  241.         SSP1CON2 = 0x00;
  242.        
  243.         SSP1CON1bits.SSPEN = 1;
  244.         return true;
  245.     }
  246.     return false;
  247. }
  248.  
  249. inline void i2c_driver_resetBus(void)
  250. {
  251.    
  252. }
  253.  
  254. inline void i2c_driver_start(void)
  255. {
  256.     SSP1CON2bits.SEN = 1;
  257. }
  258.  
  259. inline void i2c_driver_restart(void)
  260. {
  261.     SSP1CON2bits.RSEN = 1;
  262. }
  263.  
  264. inline void i2c_driver_stop(void)
  265. {
  266.     SSP1CON2bits.PEN = 1;
  267. }
  268.  
  269. inline __bit i2c_driver_isNACK(void)
  270. {
  271.     return SSP1CON2bits.ACKSTAT;
  272. }
  273.  
  274. inline void i2c_driver_startRX(void)
  275. {
  276.     SSP1CON2bits.RCEN = 1;
  277. }
  278.  
  279. inline char i2c_driver_getRXData(void)
  280. {
  281.     return SSP1BUF;
  282. }
  283.  
  284. inline void i2c_driver_setAddr(char addr)
  285. {
  286.     SSP1ADD = addr;
  287. }
  288.  
  289. inline void i2c_driver_setMask(char mask)
  290. {
  291.     SSP1MSK = mask;
  292. }
  293.  
  294. inline void i2c_driver_TXData(char d)
  295. {
  296.     SSP1BUF = d;
  297. }
  298.  
  299. inline char i2c_driver_getAddr(void)
  300. {
  301.     return SSP1ADD;
  302. }
  303.  
  304. inline void i2c_driver_sendACK(void)
  305. {
  306.     SSP1CON2bits.ACKDT = 0;
  307.     SSP1CON2bits.ACKEN = 1; // start the ACK/NACK
  308. }
  309.  
  310. inline void i2c_driver_sendNACK(void)
  311. {
  312.     SSP1CON2bits.ACKDT = 1;
  313.     SSP1CON2bits.ACKEN = 1; // start the ACK/NACK
  314. }
  315.  
  316. inline void i2c_driver_releaseClock(void)
  317. {
  318.     SSP1CON1bits.CKP = 1;
  319. }
  320.  
  321. inline __bit i2c_driver_isBufferFull(void)
  322. {
  323.     return SSP1STATbits.BF;
  324. }
  325.  
  326. inline __bit i2c_driver_isStart(void)
  327. {
  328.     return SSP1STATbits.S;
  329. }
  330.  
  331. inline __bit i2c_driver_isAddress(void)
  332. {
  333.     return !SSP1STATbits.D_nA;
  334. }
  335.  
  336. inline __bit i2c_driver_isStop(void)
  337. {
  338.     return SSP1STATbits.P;
  339. }
  340.  
  341. inline __bit i2c_driver_isData(void)
  342. {
  343.     return SSP1STATbits.D_nA;
  344. }
  345.  
  346. inline __bit i2c_driver_isRead(void)
  347. {
  348.     return SSP1STATbits.R_nW;
  349. }
  350.  
  351. inline __bit i2c_driver_isWriteCollision(void)
  352. {
  353.     return SSP1CON1bits.WCOL;
  354. }
  355.  
  356. inline __bit i2c_driver_isReceiveOverflow(void)
  357. {
  358.     return SSP1CON1bits.SSPOV;
  359. }
  360.  
  361. inline void i2c_driver_clearBusCollision(void)
  362. {
  363.     PIR2bits.BCL1IF = 0; // clear the bus collision.
  364. }
  365.  
  366. inline void i2c_driver_setBusCollisionISR(interruptHandler handler)
  367. {
  368.     i2c_driver_busCollisionISR = handler;
  369. }
  370.  
  371. inline void i2c_driver_setI2cISR(interruptHandler handler)
  372. {
  373.     i2c_driver_i2cISR = handler;
  374. }
  375.  
  376. void I2C_Init(uint32_t i2c_clk_freq)
  377. {
  378.     SSP1STAT = 0x00;
  379.     SSP1CON1 = 0x28;
  380.     SSP1CON2 = 0x00;
  381.     SSP1ADD = (_XTAL_FREQ / (4 * i2c_clk_freq)) - 1;  // set I2C clock frequency
  382. }
  383.  
  384. void I2C_Start(void)
  385. {
  386.     mssp_clearIRQ();
  387.     i2c_driver_start();
  388.     mssp_waitForEvent(500);
  389. }
  390.  
  391. void I2C_Stop(void)
  392. {
  393.     mssp_clearIRQ();
  394.     i2c_driver_stop();
  395.     mssp_waitForEvent(500);
  396. }
  397.  
  398. void I2C_Write(uint8_t i2c_data)
  399. {
  400.     mssp_clearIRQ();
  401.     SSP1BUF = i2c_data;
  402.     mssp_waitForEvent(500);
  403. }
  404.  
  405. uint8_t I2C_Read(uint8_t ack)
  406. {
  407.     uint8_t _data;
  408.     while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));  // wait for MSSP module to be free (not busy)
  409.     RCEN = 1;
  410.     while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));  // wait for MSSP module to be free (not busy)
  411.     _data = SSPBUF;  // read data from buffer
  412.     while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));  // wait for MSSP module to be free (not busy)
  413.     // send acknowledge pulse ? (depends on ack, if 1 send, otherwise don't send)
  414.     ACKDT = !ack;
  415.     ACKEN = 1;
  416.     return _data;  // return data read
  417. }
  418.  
  419. void write_to_i2c(uint8_t i2c_address, uint8_t command, uint8_t chr)
  420. {
  421.     I2C_Start();
  422.     I2C_Write(i2c_address);
  423.     I2C_Write(command);
  424.     I2C_Write(chr);
  425.     I2C_Stop();
  426. }
  427.  
  428. /**
  429.    @Param
  430.     none
  431.    @Returns
  432.     none
  433.    @Description
  434.     GPIO and peripheral I/O initialization
  435.    @Example
  436.     PIN_MANAGER_Initialize();
  437.  */
  438. void PIN_MANAGER_Initialize(void)
  439. {
  440.     /**
  441.     LATx registers
  442.     */
  443.     LATA = 0x00;
  444.  
  445.     /**
  446.     TRISx registers
  447.     */
  448.     TRISA = 0b00011111;
  449.     // RA5 is output
  450.  
  451.     /**
  452.     ANSELx registers
  453.     */
  454.     ANSELA = 0x00;
  455.  
  456.     /**
  457.     WPUx registers
  458.     */
  459.     WPUA = 0b00001111;
  460.     // RA0 is button_up, pullup
  461.     // RA1 is SCL, pullup
  462.     // RA2 is SDA, pullup
  463.     // RA3 is button_down, pullup
  464.     // RA4 is zerocross detection, no pullup
  465.     // RA5 is mosfet driver, no pullup
  466.  
  467.     // Global WPUEN bit of the OPTION register must be cleared for individual pull-ups to be enabled
  468.     // in our case we want to disable global pull-ups
  469.     OPTION_REGbits.nWPUEN = 0;
  470.  
  471.     /**
  472.     APFCONx registers
  473.     */
  474.     APFCON = 0x00;    
  475. }
  476.  
  477. /**
  478.  * @Param
  479.     none
  480.  * @Returns
  481.     none
  482.  * @Description
  483.     This macro will enable global interrupts.
  484.  * @Example
  485.     INTERRUPT_GlobalInterruptEnable();
  486.  */
  487. #define INTERRUPT_GlobalInterruptEnable() (INTCONbits.GIE = 1)
  488.  
  489. /**
  490.  * @Param
  491.     none
  492.  * @Returns
  493.     none
  494.  * @Description
  495.     This macro will disable global interrupts.
  496.  * @Example
  497.     INTERRUPT_GlobalInterruptDisable();
  498.  */
  499. #define INTERRUPT_GlobalInterruptDisable() (INTCONbits.GIE = 0)
  500. /**
  501.  * @Param
  502.     none
  503.  * @Returns
  504.     none
  505.  * @Description
  506.     This macro will enable peripheral interrupts.
  507.  * @Example
  508.     INTERRUPT_PeripheralInterruptEnable();
  509.  */
  510. #define INTERRUPT_PeripheralInterruptEnable() (INTCONbits.PEIE = 1)
  511.  
  512. /**
  513.  * @Param
  514.     none
  515.  * @Returns
  516.     none
  517.  * @Description
  518.     This macro will disable peripheral interrupts.
  519.  * @Example
  520.     INTERRUPT_PeripheralInterruptDisable();
  521.  */
  522. #define INTERRUPT_PeripheralInterruptDisable() (INTCONbits.PEIE = 0)
  523.  
  524. /**
  525.  * @Param
  526.     none
  527.  * @Returns
  528.     none
  529.  * @Description
  530.     Initializes the oscillator to the default states configured in the
  531.  *                  MCC GUI
  532.  * @Example
  533.     OSCILLATOR_Initialize(void);
  534.  */
  535. void OSCILLATOR_Initialize(void)
  536. {
  537.     // SPLLEN enabled; IRCF 32MHz_HF; SCS Clock determined by FOSC<2:0> in Configuration Word 1;
  538.     OSCCON = 0b11110000;
  539.     // TUN 0;
  540.     OSCTUNE = 0x00;
  541.     // SBOREN disabled;
  542.     BORCON = 0x00;
  543. }
  544.  
  545. /**
  546.  * @Param
  547.     none
  548.  * @Returns
  549.     none
  550.  * @Description
  551.     Initializes the WDT module to the default states configured in the
  552.  *                  MCC GUI
  553.  * @Example
  554.     WDT_Initialize(void);
  555.  */
  556. void WDT_Initialize(void)
  557. {
  558.     // WDTPS 1:65536; SWDTEN OFF;
  559.     WDTCON = 0x16;
  560. }
  561.  
  562. /**
  563.  * @Param
  564.     none
  565.  * @Returns
  566.     none
  567.  * @Description
  568.     Initializes the device to the default states configured in the
  569.  *                  MCC GUI
  570.  * @Example
  571.     SYSTEM_Initialize(void);
  572.  */
  573. void SYSTEM_Initialize(void)
  574. {
  575.  
  576.     PIN_MANAGER_Initialize();
  577.     OSCILLATOR_Initialize();
  578.     WDT_Initialize();
  579. }
  580.  
  581. /*------------------------------ SSD1306 128x64 definitions ---------------------------------*/
  582.  
  583. #define SSD1306_I2C_ADDRESS      (0x3C << 1)
  584.  
  585. #define SSD1306_LCDWIDTH             128
  586. #define SSD1306_LCDHEIGHT            64
  587.  
  588. #define SSD1306_NORMALDISPLAY        0xA6
  589. #define SSD1306_INVERTDISPLAY        0xA7
  590. #define SSD1306_DISPLAYOFF           0xAE
  591. #define SSD1306_DISPLAYON            0xAF
  592. #define SSD1306_SETDISPLAYOFFSET     0xD3
  593. #define SSD1306_SETCOMPINS           0xDA
  594. #define SSD1306_SETVCOMDETECT        0xDB
  595. #define SSD1306_SETDISPLAYCLOCKDIV   0xD5
  596. #define SSD1306_SETPRECHARGE         0xD9
  597. #define SSD1306_SETCONTRAST          0x81
  598. #define SSD1306_DISPLAYALLON_RESUME  0xA4
  599. #define SSD1306_SETMULTIPLEX         0xA8
  600. #define SSD1306_SETLOWCOLUMN         0x00
  601. #define SSD1306_SETHIGHCOLUMN        0x10
  602. #define SSD1306_SETSTARTLINE         0x40
  603. #define SSD1306_MEMORYMODE           0x20
  604. #define SSD1306_COLUMNADDR           0x21
  605. #define SSD1306_PAGEADDR             0x22
  606. #define SSD1306_COMSCANINC           0xC0
  607. #define SSD1306_COMSCANDEC           0xC8
  608. #define SSD1306_SEGREMAP             0xA0
  609. #define SSD1306_CHARGEPUMP           0x8D
  610. #define SSD1306_EXTERNALVCC          0x01
  611. #define SSD1306_SWITCHCAPVCC         0x02
  612.  
  613. // Scrolling #defines
  614. #define SSD1306_ACTIVATE_SCROLL      0x2F
  615. #define SSD1306_DEACTIVATE_SCROLL                    0x2E
  616. #define SSD1306_SET_VERTICAL_SCROLL_AREA             0xA3
  617. #define SSD1306_RIGHT_HORIZONTAL_SCROLL              0x26
  618. #define SSD1306_LEFT_HORIZONTAL_SCROLL               0x27
  619. #define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29
  620. #define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL  0x2A
  621.  
  622. #define Set_Page_Start_Address_CMD                   0xB0
  623.  
  624. #define y_max   8
  625.  
  626. #define CMD 0x00
  627. #define DAT 0x40
  628.  
  629. // Init sequence for Adafruit 128x64 OLED module
  630. uint8_t ssd1306_init_sequence[25] = {
  631.     SSD1306_DISPLAYOFF,
  632.     SSD1306_SETDISPLAYCLOCKDIV,
  633.     0x80,                             // the suggested ratio 0x80
  634.     SSD1306_SETMULTIPLEX,
  635.     0x3F,                             // ratio 64
  636.     SSD1306_SETDISPLAYOFFSET,
  637.     0x0,                              // no offset
  638.     SSD1306_SETSTARTLINE | 0x0,       // line #0
  639.     SSD1306_CHARGEPUMP,
  640.     0x14,                             // internal vcc
  641.     SSD1306_MEMORYMODE,
  642.     0x02,                             // page mode
  643.     SSD1306_SEGREMAP | 0x1,           // column 127 mapped to SEG0
  644.     SSD1306_COMSCANDEC,               // column scan direction reversed
  645.     SSD1306_SETCOMPINS,
  646.     0x12,                             // alt COM pins, disable remap
  647.     SSD1306_SETCONTRAST,
  648.     0x7F,                             // contrast level 127
  649.     SSD1306_SETPRECHARGE,
  650.     0xF1,                             // pre-charge period (1, 15)
  651.     SSD1306_SETVCOMDETECT,
  652.     0x40,                             // vcomh regulator level
  653.     SSD1306_DISPLAYALLON_RESUME,
  654.     SSD1306_NORMALDISPLAY,
  655.     SSD1306_DISPLAYON
  656. };
  657.  
  658. void ssd1306_write(uint8_t addr, uint8_t cmd)
  659. {
  660.     write_to_i2c(SSD1306_I2C_ADDRESS, addr, cmd);
  661. }
  662.  
  663. void ssd1306_init(void)
  664. {
  665.     uint8_t i;
  666.    
  667.     for (i=0; i < 25; ++i)
  668.         ssd1306_write(CMD, ssd1306_init_sequence[i]);
  669. }
  670.  
  671. #if 0
  672. #define FONT_WIDTH 42
  673. #define FONT_HEIGHT 64
  674.  
  675. const uint8_t font_bitmap[10][336] = {
  676.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0,
  677.     0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0,
  678.     0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  679.     0xE0, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x0F, 0x07, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01,
  680.     0x01, 0x01, 0x01, 0x03, 0x03, 0x07, 0x0F, 0x1F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF0, 0x80,
  681.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
  682.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  683.     0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
  684.     0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  685.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
  686.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
  687.     0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  688.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
  689.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x80, 0x00,
  690.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  691.     0x80, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  692.     0x00, 0x00, 0x03, 0x0F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xF0, 0xE0, 0xE0, 0xC0, 0xC0,
  693.     0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F,
  694.     0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  695.     0x00, 0x01, 0x03, 0x03, 0x07, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
  696.     0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0
  697.  
  698.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  699.     0x80, 0x80, 0x80, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
  700.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  701.     0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0x7E, 0x7E, 0x7E, 0x3F, 0x3F, 0x1F, 0x1F, 0x1F, 0x0F, 0xFF, 0xFF,
  702.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  703.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
  704.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
  705.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  706.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  707.     0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  708.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  709.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
  710.     0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  711.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  712.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
  713.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  714.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  715.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  716.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  717.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  718.     0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 1
  719.  
  720.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF8,
  721.     0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xC0, 0xC0,
  722.     0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF8, 0xFC,
  723.     0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x0F, 0x07, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  724.     0x01, 0x01, 0x03, 0x03, 0x07, 0x0F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xC0, 0x00,
  725.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x00, 0x00,
  726.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  727.     0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  728.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  729.     0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x0F,
  730.     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  731.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF,
  732.     0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  733.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8,
  734.     0xFE, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  735.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  736.     0xE0, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xE7, 0xE3, 0xE1, 0xE0, 0xE0, 0xE0, 0xE0,
  737.     0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
  738.     0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  739.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  740.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00}, // 2
  741.  
  742.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0,
  743.     0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0,
  744.     0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0,
  745.     0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x0F, 0x07, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
  746.     0x01, 0x01, 0x01, 0x03, 0x03, 0x07, 0x0F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xE0, 0x00,
  747.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00,
  748.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  749.     0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  750.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0,
  751.     0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFE, 0xFF, 0xBF, 0x1F, 0x1F, 0x0F,
  752.     0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  753.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  754.     0x07, 0x07, 0x07, 0x0F, 0x1F, 0x3F, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, 0xF8, 0xE0, 0x80, 0x00, 0x00,
  755.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00,
  756.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  757.     0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  758.     0x03, 0x0F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0,
  759.     0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F,
  760.     0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  761.     0x01, 0x03, 0x03, 0x07, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
  762.     0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 3
  763.  
  764.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  765.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
  766.     0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  767.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xFC,
  768.     0xFE, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
  769.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  770.     0x00, 0x80, 0xE0, 0xF0, 0xFC, 0xFE, 0xFF, 0xFF, 0x3F, 0x1F, 0x07, 0x03, 0x00, 0x00, 0xFF, 0xFF,
  771.     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  772.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xFC, 0xFE, 0xFF, 0xFF, 0x3F, 0x1F, 0x07,
  773.     0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
  774.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xFC, 0xFF,
  775.     0xFF, 0xFF, 0x3F, 0x1F, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  776.     0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  777.     0x00, 0x00, 0x00, 0x7C, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E,
  778.     0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF,
  779.     0xFF, 0xFF, 0xFF, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00,
  780.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  781.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
  782.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  783.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  784.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 4
  785.  
  786.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
  787.     0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
  788.     0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  789.     0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  790.     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00,
  791.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  792.     0xFF, 0x07, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
  793.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  794.     0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3F, 0x3F, 0x1F, 0x1F,
  795.     0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, 0xF8, 0xF0,
  796.     0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  797.     0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  798.     0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00,
  799.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00,
  800.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  801.     0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  802.     0x01, 0x07, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0,
  803.     0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F,
  804.     0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  805.     0x01, 0x03, 0x03, 0x07, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
  806.     0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 5
  807.  
  808.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  809.     0x80, 0x80, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00,
  810.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  811.     0x00, 0x00, 0x80, 0xC0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 0x1F, 0x0F, 0x0F,
  812.     0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  813.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
  814.     0x1F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
  815.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  816.     0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xF8, 0xFC, 0xFE, 0x7E, 0x3F, 0x3F,
  817.     0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFE, 0xFC, 0xFC, 0xF8,
  818.     0xF0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
  819.     0xFF, 0xFF, 0xFF, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  820.     0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00,
  821.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x80, 0x00,
  822.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  823.     0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  824.     0x00, 0x00, 0x03, 0x0F, 0x1F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0,
  825.     0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F,
  826.     0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  827.     0x00, 0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
  828.     0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 6
  829.  
  830.     {0x00, 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
  831.     0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
  832.     0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07,
  833.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
  834.     0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x87, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
  835.     0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  836.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0,
  837.     0xF0, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  838.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  839.     0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x0F, 0x03, 0x00,
  840.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  841.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF8, 0xFE, 0xFF,
  842.     0xFF, 0xFF, 0x7F, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  843.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  844.     0x00, 0x00, 0xC0, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00,
  845.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  846.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F,
  847.     0x1F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  848.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  849.     0x08, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  850.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 7
  851.  
  852.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0,
  853.     0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0,
  854.     0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  855.     0xF0, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x0F, 0x07, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01,
  856.     0x01, 0x01, 0x01, 0x03, 0x03, 0x07, 0x0F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0x80,
  857.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  858.     0xF1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  859.     0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  860.     0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0xBF, 0xFF, 0xFE, 0xFC, 0xF8, 0xF8,
  861.     0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0x3F, 0x1F, 0x0F,
  862.     0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF8,
  863.     0xFC, 0xFE, 0xFE, 0xFF, 0x7F, 0x1F, 0x0F, 0x0F, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
  864.     0x03, 0x07, 0x07, 0x0F, 0x0F, 0x1F, 0x3F, 0xFF, 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xC0, 0x00, 0x00,
  865.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0x00, 0x00,
  866.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  867.     0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  868.     0x00, 0x07, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xF0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0,
  869.     0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F,
  870.     0x1F, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  871.     0x01, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
  872.     0x0F, 0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 8
  873.  
  874.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0,
  875.     0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0x80, 0x00,
  876.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0,
  877.     0xF0, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x0F, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03,
  878.     0x03, 0x03, 0x07, 0x07, 0x0F, 0x1F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF0, 0xE0, 0x00, 0x00,
  879.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01,
  880.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  881.     0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  882.     0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
  883.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xFF, 0xFF, 0xFF,
  884.     0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07,
  885.     0x0F, 0x1F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFE, 0xFC, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
  886.     0xFC, 0xFC, 0x7E, 0x7F, 0x3F, 0x1F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00,
  887.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  888.     0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0,
  889.     0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  890.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0,
  891.     0xE0, 0xF0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x03, 0x00, 0x00,
  892.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  893.     0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x01,
  894.     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // 9
  895. };
  896.  
  897. // run-length encoded fonts
  898. // https://eleif.net/rle.html
  899. const uint8_t font_bitmap[] = {
  900.     0x0A,0x00,0x01,0x80,0x01,0xC0,0x02,0xE0,0x03,0xF0,0x09,0xF8,0x03,0xF0,0x02,0xE0,0x02,0xC0,0x01,0x80,0x0E,0x00,0x01,0xE0,0x01,0xF8,0x01,0xFE,0x04,0xFF,0x01,0x3F,0x01,0x0F,0x01,0x07,0x02,0x03,0x07,0x01,0x02,0x03,0x01,0x07,0x01,0x0F,0x01,0x1F,0x01,0x7F,0x03,0xFF,0x01,0xFE,0x01,0xFC,0x01,0xF0,0x01,0x80,0x08,0x00,0x01,0xC0,0x06,0xFF,0x01,0x1F,0x13,0x00,0x01,0x07,0x06,0xFF,0x01,0xF0,0x07,0x00,0x07,0xFF,0x15,0x00,0x07,0xFF,0x07,0x00,0x07,0xFF,0x15,0x00,0x07,0xFF,0x07,0x00,0x01,0x01,0x01,0x7F,0x05,0xFF,0x01,0xFE,0x01,0x80,0x11,0x00,0x01,0x80,0x01,0xF8,0x06,0xFF,0x01,0x03,0x09,0x00,0x01,0x03,0x01,0x0F,0x01,0x3F,0x01,0x7F,0x03,0xFF,0x01,0xFE,0x01,0xF8,0x01,0xF0,0x02,0xE0,0x07,0xC0,0x02,0xE0,0x01,0xF0,0x01,0xF8,0x01,0xFC,0x03,0xFF,0x01,0x7F,0x01,0x3F,0x01,0x1F,0x01,0x07,0x10,0x00,0x01,0x01,0x02,0x03,0x03,0x07,0x09,0x0F,0x03,0x07,0x02,0x03,0x01,0x01,0x0A,0x00, // 0
  901.     0x10,0x00,0x03,0x80,0x03,0xC0,0x03,0xE0,0x02,0xF0,0x15,0x00,0x02,0xF8,0x03,0xFC,0x03,0x7E,0x02,0x3F,0x03,0x1F,0x01,0x0F,0x07,0xFF,0x15,0x00,0x02,0x01,0x0C,0x00,0x07,0xFF,0x23,0x00,0x07,0xFF,0x23,0x00,0x07,0xFF,0x23,0x00,0x07,0xFF,0x23,0x00,0x07,0xFF,0x23,0x00,0x07,0x07,0x0F,0x00, // 1
  902.     0x08,0x00,0x01,0x80,0x01,0xC0,0x02,0xE0,0x03,0xF0,0x0A,0xF8,0x04,0xF0,0x01,0xE0,0x02,0xC0,0x01,0x80,0x0C,0x00,0x01,0xC0,0x01,0xF8,0x01,0xFC,0x01,0xFE,0x03,0xFF,0x01,0x7F,0x01,0x1F,0x01,0x0F,0x01,0x07,0x02,0x03,0x08,0x01,0x02,0x03,0x01,0x07,0x01,0x0F,0x01,0x1F,0x05,0xFF,0x01,0xFE,0x01,0xF8,0x01,0xC0,0x07,0x00,0x01,0x10,0x06,0x0F,0x01,0x07,0x13,0x00,0x01,0xC0,0x06,0xFF,0x01,0x1F,0x1C,0x00,0x01,0x80,0x01,0xC0,0x01,0xE0,0x01,0xF0,0x01,0xFC,0x03,0xFF,0x01,0x7F,0x01,0x3F,0x01,0x0F,0x01,0x03,0x17,0x00,0x01,0x80,0x01,0xC0,0x01,0xE0,0x01,0xF0,0x01,0xF8,0x01,0xFC,0x01,0xFE,0x01,0xFF,0x01,0x7F,0x01,0x3F,0x01,0x1F,0x01,0x0F,0x01,0x07,0x01,0x03,0x15,0x00,0x01,0x80,0x01,0xC0,0x01,0xE0,0x01,0xF0,0x01,0xF8,0x01,0xFE,0x02,0xFF,0x01,0x7F,0x01,0x3F,0x01,0x1F,0x01,0x0F,0x01,0x07,0x01,0x01,0x17,0x00,0x01,0xE0,0x01,0xF8,0x01,0xFC,0x01,0xFE,0x04,0xFF,0x01,0xEF,0x01,0xE7,0x01,0xE3,0x01,0xE1,0x17,0xE0,0x07,0x00,0x23,0x07,0x03,0x00, // 2
  903.     0x09,0x00,0x01,0x80,0x01,0xC0,0x02,0xE0,0x03,0xF0,0x0A,0xF8,0x03,0xF0,0x02,0xE0,0x01,0xC0,0x01,0x80,0x0D,0x00,0x01,0xC0,0x01,0xF0,0x01,0xFC,0x01,0xFE,0x03,0xFF,0x01,0x7F,0x01,0x1F,0x01,0x0F,0x01,0x07,0x02,0x03,0x08,0x01,0x02,0x03,0x01,0x07,0x01,0x0F,0x01,0x1F,0x04,0xFF,0x01,0xFE,0x01,0xFC,0x01,0xE0,0x09,0x00,0x07,0x03,0x12,0x00,0x01,0x80,0x06,0xFF,0x01,0x7F,0x14,0x00,0x09,0xF0,0x02,0xF8,0x02,0xFC,0x01,0xFE,0x01,0xFF,0x01,0xBF,0x02,0x1F,0x01,0x0F,0x01,0x07,0x01,0x01,0x15,0x00,0x09,0x03,0x03,0x07,0x01,0x0F,0x01,0x1F,0x01,0x3F,0x02,0xFF,0x02,0xFE,0x01,0xFC,0x01,0xF8,0x01,0xE0,0x01,0x80,0x08,0x00,0x07,0xE0,0x14,0x00,0x07,0xFF,0x08,0x00,0x01,0x03,0x01,0x0F,0x01,0x3F,0x01,0x7F,0x03,0xFF,0x01,0xFE,0x01,0xF8,0x02,0xF0,0x02,0xE0,0x08,0xC0,0x02,0xE0,0x01,0xF0,0x01,0xF8,0x01,0xFC,0x01,0xFE,0x03,0xFF,0x01,0x7F,0x01,0x1F,0x01,0x0F,0x01,0x01,0x0D,0x00,0x02,0x01,0x02,0x03,0x03,0x07,0x0A,0x0F,0x03,0x07,0x02,0x03,0x01,0x01,0x0A,0x00, // 3
  904.     0x17,0x00,0x01,0x80,0x01,0xC0,0x08,0xF0,0x1B,0x00,0x01,0x80,0x01,0xE0,0x01,0xF0,0x01,0xFC,0x01,0xFE,0x02,0xFF,0x01,0x3F,0x07,0xFF,0x16,0x00,0x01,0x80,0x01,0xE0,0x01,0xF0,0x01,0xFC,0x01,0xFE,0x02,0xFF,0x01,0x3F,0x01,0x1F,0x01,0x07,0x01,0x03,0x02,0x00,0x07,0xFF,0x11,0x00,0x01,0x80,0x01,0xE0,0x01,0xF0,0x01,0xFC,0x01,0xFE,0x02,0xFF,0x01,0x3F,0x01,0x1F,0x01,0x07,0x01,0x03,0x07,0x00,0x07,0xFF,0x0C,0x00,0x01,0x80,0x01,0xE0,0x01,0xF0,0x01,0xFC,0x03,0xFF,0x01,0x3F,0x01,0x1F,0x01,0x07,0x01,0x03,0x0C,0x00,0x07,0xFF,0x0A,0x00,0x01,0x7C,0x07,0x7F,0x11,0x7E,0x07,0xFF,0x08,0x7E,0x1B,0x00,0x07,0xFF,0x23,0x00,0x07,0x07,0x09,0x00, // 4
  905.     0x08,0x00,0x1D,0xF0,0x0C,0x00,0x01,0xC0,0x06,0xFF,0x17,0x03,0x0C,0x00,0x06,0xFF,0x01,0x07,0x03,0x00,0x09,0x80,0x16,0x00,0x07,0xFF,0x01,0x7E,0x02,0x3F,0x08,0x1F,0x02,0x3F,0x01,0x7F,0x02,0xFF,0x02,0xFE,0x01,0xFC,0x01,0xF8,0x01,0xF0,0x01,0xE0,0x01,0xC0,0x10,0x00,0x02,0x01,0x10,0x00,0x01,0x01,0x01,0x03,0x01,0x0F,0x06,0xFF,0x01,0xF8,0x08,0x00,0x06,0xE0,0x01,0xC0,0x13,0x00,0x01,0x80,0x07,0xFF,0x08,0x00,0x01,0x01,0x01,0x07,0x01,0x1F,0x01,0x3F,0x01,0x7F,0x02,0xFF,0x01,0xFE,0x01,0xFC,0x01,0xF8,0x01,0xF0,0x02,0xE0,0x07,0xC0,0x02,0xE0,0x02,0xF0,0x01,0xF8,0x01,0xFE,0x03,0xFF,0x01,0x7F,0x01,0x3F,0x01,0x1F,0x01,0x07,0x0F,0x00,0x01,0x01,0x02,0x03,0x03,0x07,0x0A,0x0F,0x03,0x07,0x02,0x03,0x01,0x01,0x0A,0x00, // 5
  906.     0x10,0x00,0x02,0x80,0x02,0xC0,0x04,0xE0,0x07,0xF0,0x13,0x00,0x01,0x80,0x01,0xC0,0x01,0xF0,0x01,0xF8,0x01,0xFC,0x01,0xFE,0x02,0xFF,0x01,0x7F,0x01,0x3F,0x02,0x1F,0x02,0x0F,0x03,0x07,0x06,0x03,0x10,0x00,0x01,0xC0,0x01,0xF8,0x01,0xFE,0x04,0xFF,0x01,0x1F,0x01,0x07,0x01,0x01,0x03,0x00,0x09,0x80,0x13,0x00,0x01,0xF8,0x06,0xFF,0x01,0xF9,0x01,0xF8,0x01,0xFC,0x01,0xFE,0x01,0x7E,0x02,0x3F,0x07,0x1F,0x02,0x3F,0x01,0x7F,0x02,0xFF,0x01,0xFE,0x02,0xFC,0x01,0xF8,0x01,0xF0,0x01,0xC0,0x01,0x80,0x09,0x00,0x07,0xFF,0x01,0x07,0x01,0x03,0x01,0x01,0x0F,0x00,0x01,0x01,0x01,0x07,0x01,0x7F,0x05,0xFF,0x01,0xFC,0x08,0x00,0x01,0x0F,0x06,0xFF,0x01,0xF0,0x01,0x80,0x12,0x00,0x01,0xF0,0x06,0xFF,0x01,0x07,0x09,0x00,0x01,0x03,0x01,0x0F,0x01,0x1F,0x01,0x7F,0x03,0xFF,0x01,0xFE,0x01,0xF8,0x02,0xF0,0x02,0xE0,0x06,0xC0,0x02,0xE0,0x01,0xF0,0x01,0xF8,0x01,0xFC,0x03,0xFF,0x01,0x7F,0x01,0x3F,0x01,0x1F,0x01,0x07,0x01,0x01,0x0F,0x00,0x02,0x01,0x02,0x03,0x02,0x07,0x09,0x0F,0x03,0x07,0x02,0x03,0x01,0x01,0x0A,0x00, // 6
  907.     0x03,0x00,0x25,0xE0,0x05,0x00,0x1B,0x07,0x01,0x87,0x01,0xE7,0x05,0xFF,0x01,0x3F,0x01,0x0F,0x01,0x03,0x1D,0x00,0x01,0xC0,0x01,0xF0,0x01,0xFC,0x03,0xFF,0x01,0x7F,0x01,0x1F,0x01,0x07,0x01,0x01,0x1C,0x00,0x01,0x80,0x01,0xF0,0x01,0xFC,0x04,0xFF,0x01,0x3F,0x01,0x0F,0x01,0x03,0x1C,0x00,0x01,0x80,0x01,0xE0,0x01,0xF8,0x01,0xFE,0x03,0xFF,0x01,0x7F,0x01,0x1F,0x01,0x07,0x1D,0x00,0x01,0xC0,0x01,0xF0,0x01,0xFE,0x04,0xFF,0x01,0x3F,0x01,0x0F,0x01,0x01,0x1C,0x00,0x01,0xC0,0x01,0xF0,0x01,0xFC,0x04,0xFF,0x01,0x7F,0x01,0x1F,0x01,0x03,0x1E,0x00,0x01,0x08,0x01,0x0E,0x05,0x0F,0x01,0x07,0x01,0x01,0x17,0x00, // 7
  908.     0x0A,0x00,0x01,0x80,0x01,0xC0,0x02,0xE0,0x03,0xF0,0x09,0xF8,0x03,0xF0,0x02,0xE0,0x02,0xC0,0x01,0x80,0x0E,0x00,0x01,0xF0,0x01,0xFC,0x01,0xFE,0x04,0xFF,0x01,0x3F,0x01,0x0F,0x01,0x07,0x02,0x03,0x07,0x01,0x02,0x03,0x01,0x07,0x01,0x0F,0x01,0x1F,0x05,0xFF,0x01,0xFC,0x01,0xF0,0x01,0x80,0x09,0x00,0x01,0x04,0x06,0xFF,0x01,0xF1,0x01,0x80,0x10,0x00,0x01,0xE0,0x06,0xFF,0x01,0x1F,0x0B,0x00,0x01,0x03,0x01,0x07,0x01,0x0F,0x01,0x1F,0x01,0x3F,0x01,0xBF,0x01,0xFF,0x01,0xFE,0x01,0xFC,0x02,0xF8,0x07,0xF0,0x02,0xF8,0x01,0xFC,0x01,0xFE,0x02,0xFF,0x01,0x3F,0x01,0x1F,0x01,0x0F,0x01,0x07,0x01,0x03,0x0B,0x00,0x01,0xC0,0x01,0xE0,0x01,0xF8,0x01,0xFC,0x02,0xFE,0x01,0xFF,0x01,0x7F,0x01,0x1F,0x02,0x0F,0x02,0x07,0x07,0x03,0x02,0x07,0x02,0x0F,0x01,0x1F,0x01,0x3F,0x02,0xFF,0x01,0xFE,0x01,0xFC,0x01,0xF8,0x01,0xF0,0x01,0xC0,0x08,0x00,0x01,0xFE,0x06,0xFF,0x01,0x81,0x13,0x00,0x01,0x01,0x07,0xFF,0x08,0x00,0x01,0x07,0x01,0x1F,0x01,0x3F,0x01,0x7F,0x03,0xFF,0x01,0xFC,0x01,0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x01,0xF8,0x01,0xFC,0x04,0xFF,0x01,0x7F,0x01,0x1F,0x01,0x0F,0x01,0x01,0x0D,0x00,0x01,0x01,0x02,0x03,0x04,0x07,0x0A,0x0F,0x03,0x07,0x02,0x03,0x01,0x01,0x09,0x00, // 8
  909.     0x0A,0x00,0x01,0x80,0x02,0xC0,0x03,0xE0,0x09,0xF0,0x03,0xE0,0x02,0xC0,0x01,0x80,0x10,0x00,0x01,0xC0,0x01,0xF0,0x01,0xFC,0x01,0xFE,0x03,0xFF,0x01,0x7F,0x01,0x1F,0x01,0x0F,0x03,0x07,0x06,0x03,0x02,0x07,0x01,0x0F,0x01,0x1F,0x01,0x3F,0x03,0xFF,0x01,0xFE,0x01,0xFC,0x01,0xF0,0x01,0xE0,0x0A,0x00,0x01,0xFE,0x06,0xFF,0x01,0x01,0x12,0x00,0x01,0x07,0x06,0xFF,0x01,0xF8,0x08,0x00,0x01,0x1F,0x06,0xFF,0x01,0xF0,0x01,0xC0,0x10,0x00,0x01,0x80,0x01,0xE0,0x07,0xFF,0x0A,0x00,0x01,0x03,0x01,0x07,0x01,0x0F,0x01,0x1F,0x01,0x3F,0x02,0x7F,0x01,0xFF,0x01,0xFE,0x02,0xFC,0x07,0xF8,0x02,0xFC,0x01,0x7E,0x01,0x7F,0x01,0x3F,0x01,0x1F,0x01,0x0F,0x06,0xFF,0x01,0x7F,0x13,0x00,0x08,0x01,0x05,0x00,0x01,0xC0,0x01,0xF0,0x01,0xFE,0x04,0xFF,0x01,0x3F,0x01,0x07,0x10,0x00,0x07,0xC0,0x03,0xE0,0x02,0xF0,0x02,0xF8,0x01,0xFC,0x01,0xFE,0x02,0xFF,0x01,0x7F,0x01,0x3F,0x01,0x1F,0x01,0x0F,0x01,0x03,0x13,0x00,0x08,0x0F,0x04,0x07,0x02,0x03,0x02,0x01,0x0F,0x00 // 9
  910. };
  911.  
  912. const uint16_t font_bitmap_offsets[] = {0, 0xac, 0xe4, 0x19c, 0x256, 0x2d2, 0x35e, 0x422, 0x498, 0x580};
  913.  
  914. void ssd1306_draw_font(uint8_t x, uint8_t y, size_t ch_sz, uint16_t of)
  915. {
  916.     size_t tt = 0;
  917.     uint8_t x_pos = x;
  918.     uint8_t y_pos = 0;
  919.  
  920.     uint8_t num_bytes = 0;
  921.     uint8_t bytes = 0;
  922.     uint16_t ii = 0;
  923.     uint16_t ofset = font_bitmap_offsets[of];;
  924.  
  925.     for(tt=0; tt<ch_sz;)
  926.     {
  927.         num_bytes = font_bitmap[ofset++];
  928.         bytes = font_bitmap[ofset++];
  929.  
  930.         for (ii=0; ii<num_bytes; ++ii)
  931.         {
  932.             if (x_pos >= (x + FONT_WIDTH))
  933.             {
  934.                 x_pos = x;
  935.                 y_pos++;
  936.             }
  937.  
  938.             ssd1306_write(CMD, Set_Page_Start_Address_CMD + y_pos);        // set row
  939.             ssd1306_write(CMD, SSD1306_SETLOWCOLUMN | (x_pos & 0xf));      // set lower column address
  940.             ssd1306_write(CMD, SSD1306_SETHIGHCOLUMN | (x_pos >> 4));      // set higher column address
  941.  
  942.             ssd1306_write(DAT, (uint8_t)bytes);
  943.             tt++;
  944.             x_pos++;
  945.         }
  946.     }
  947. }
  948.  
  949. // 336 is sizeof run-length decoded font bitmap!
  950. void draw_temperature(uint16_t temp)
  951. {
  952.     if (temp == 0)
  953.     {
  954.         ssd1306_draw_font(0, 0, 336, 0);
  955.         ssd1306_draw_font(FONT_WIDTH, 0, 336, 0);
  956.         ssd1306_draw_font(2*FONT_WIDTH, 0, 336, 0);
  957.     }
  958.     else if (temp > 0 && temp < 10)
  959.     {
  960.         ssd1306_draw_font(0, 0, 336, 0);
  961.         ssd1306_draw_font(FONT_WIDTH, 0, 336, 0);
  962.         ssd1306_draw_font(2*FONT_WIDTH, 0, 336, temp);
  963.     }
  964.     else if (temp >= 10 && temp < 100)
  965.     {
  966.         ssd1306_draw_font(0, 0, 336, 0);
  967.         ssd1306_draw_font(FONT_WIDTH, 0, 336, (temp/10)%10);
  968.         ssd1306_draw_font(2*FONT_WIDTH, 0, 336, temp%10);
  969.     }
  970.     else if (temp >= 100 && temp < 1000)
  971.     {
  972.         ssd1306_draw_font(0, 0, 336, (temp/100)%10);
  973.         ssd1306_draw_font(FONT_WIDTH, 0, 336, (temp/10)%10);
  974.         ssd1306_draw_font(2*FONT_WIDTH, 0, 336, temp%10);
  975.     }
  976.     else
  977.     {
  978.         ssd1306_draw_font(0, 0, 336, 9);
  979.         ssd1306_draw_font(FONT_WIDTH, 0, 336, 9);
  980.         ssd1306_draw_font(2*FONT_WIDTH, 0, 336, 9);
  981.     }
  982. }
  983. #endif
  984.  
  985. #define FONT_WIDTH 21
  986. #define FONT_HEIGHT 32
  987.  
  988. const uint8_t font_bitmap[] = {
  989.     0x03,0x00,0x01,0xE0,0x01,0xF0,0x01,0xF8,0x01,0x7C,0x01,0x1C,0x01,0x1E,0x03,0x0E,0x01,0x1E,0x01,0x1C,0x01,0x3C,0x02,0xF8,0x01,0xE0,0x01,0x80,0x04,0x00,0x03,0xFF,0x01,0x03,0x09,0x00,0x01,0x01,0x03,0xFF,0x04,0x00,0x01,0x7F,0x02,0xFF,0x01,0xF0,0x09,0x00,0x01,0xE0,0x03,0xFF,0x05,0x00,0x01,0x03,0x01,0x07,0x01,0x0F,0x01,0x1F,0x01,0x1C,0x01,0x3C,0x03,0x38,0x01,0x3C,0x01,0x1C,0x01,0x1E,0x01,0x0F,0x01,0x07,0x01,0x03,0x03,0x00, // 0
  990.     0x03,0x00,0x02,0xE0,0x03,0x70,0x02,0x38,0x01,0xF8,0x02,0xFC,0x12,0x00,0x03,0xFF,0x12,0x00,0x03,0xFF,0x12,0x00,0x03,0x1F,0x08,0x00, // 1
  991.     0x01,0x00,0x01,0x80,0x01,0xE0,0x01,0xF0,0x01,0xF8,0x01,0x3C,0x01,0x1C,0x01,0x1E,0x04,0x0E,0x01,0x1C,0x01,0x3C,0x01,0xFC,0x01,0xF8,0x01,0xF0,0x01,0xE0,0x04,0x00,0x03,0x03,0x01,0x01,0x06,0x00,0x01,0x80,0x01,0xC0,0x01,0xE0,0x01,0xF8,0x01,0x7F,0x01,0x3F,0x01,0x0F,0x07,0x00,0x01,0x80,0x01,0xC0,0x01,0xE0,0x01,0xF0,0x01,0x78,0x01,0x3C,0x01,0x1E,0x01,0x0F,0x01,0x07,0x01,0x03,0x01,0x01,0x08,0x00,0x01,0x1E,0x03,0x1F,0x01,0x1D,0x0C,0x1C,0x02,0x00, // 2
  992.     0x02,0x00,0x01,0xC0,0x01,0xF0,0x01,0xF8,0x01,0x7C,0x01,0x3C,0x01,0x1C,0x04,0x0E,0x01,0x1E,0x01,0x1C,0x01,0x3C,0x01,0xF8,0x01,0xF0,0x01,0xE0,0x05,0x00,0x03,0x01,0x02,0x00,0x05,0xC0,0x02,0xE0,0x01,0xF8,0x02,0x3F,0x01,0x0F,0x05,0x00,0x03,0xC0,0x02,0x00,0x06,0x01,0x01,0x03,0x01,0x07,0x02,0xFF,0x01,0xFE,0x01,0xF8,0x04,0x00,0x01,0x03,0x01,0x07,0x01,0x0F,0x01,0x1F,0x02,0x1C,0x04,0x38,0x01,0x3C,0x01,0x1C,0x01,0x1E,0x02,0x0F,0x01,0x03,0x03,0x00, // 3
  993.     0x09,0x00,0x01,0xC0,0x01,0xE0,0x01,0xF8,0x01,0x7C,0x03,0xFC,0x09,0x00,0x01,0xC0,0x01,0xE0,0x01,0xF8,0x01,0x7C,0x01,0x1F,0x01,0x0F,0x01,0x03,0x01,0x01,0x01,0x00,0x03,0xFF,0x05,0x00,0x01,0x60,0x01,0x78,0x01,0x7C,0x02,0x7F,0x01,0x73,0x01,0x71,0x06,0x70,0x03,0xFF,0x04,0x70,0x0E,0x00,0x03,0x1F,0x05,0x00, // 4
  994.     0x03,0x00,0x01,0x80,0x03,0xFC,0x0B,0x1C,0x06,0x00,0x03,0xFF,0x01,0x71,0x01,0x70,0x04,0x38,0x01,0x78,0x02,0xF0,0x01,0xE0,0x01,0xC0,0x01,0x80,0x05,0x00,0x03,0xC0,0x09,0x00,0x01,0x01,0x03,0xFF,0x01,0xFE,0x04,0x00,0x01,0x01,0x01,0x07,0x01,0x0F,0x01,0x1F,0x01,0x1E,0x01,0x1C,0x04,0x38,0x01,0x3C,0x01,0x1C,0x01,0x1F,0x01,0x0F,0x01,0x07,0x01,0x03,0x03,0x00, // 5
  995.     0x04,0x00,0x01,0x80,0x01,0xE0,0x02,0xF0,0x01,0x78,0x01,0x38,0x01,0x3C,0x04,0x1C,0x08,0x00,0x01,0xF8,0x02,0xFF,0x01,0xEF,0x01,0xE1,0x02,0x70,0x03,0x38,0x01,0x78,0x01,0x70,0x01,0xF0,0x02,0xE0,0x01,0x80,0x05,0x00,0x03,0xFF,0x01,0xC1,0x09,0x00,0x01,0xC7,0x02,0xFF,0x01,0xFE,0x05,0x00,0x01,0x03,0x01,0x07,0x01,0x0F,0x01,0x1F,0x01,0x1C,0x01,0x3C,0x03,0x38,0x01,0x3C,0x01,0x1C,0x01,0x1E,0x01,0x0F,0x01,0x07,0x01,0x03,0x03,0x00, // 6
  996.     0x01,0x00,0x0E,0x1C,0x01,0xDC,0x02,0xFC,0x01,0x7C,0x01,0x1C,0x0C,0x00,0x01,0x80,0x01,0xE0,0x01,0xF8,0x01,0xFE,0x01,0x3F,0x01,0x07,0x01,0x01,0x0B,0x00,0x01,0xC0,0x01,0xF8,0x01,0xFE,0x01,0x7F,0x01,0x0F,0x01,0x03,0x0C,0x00,0x01,0x30,0x01,0x3C,0x01,0x3F,0x01,0x1F,0x01,0x07,0x01,0x01,0x0A,0x00, // 7
  997.     0x03,0x00,0x01,0xE0,0x01,0xF0,0x01,0xF8,0x01,0x7C,0x01,0x1C,0x01,0x1E,0x03,0x0E,0x01,0x1E,0x01,0x1C,0x01,0x3C,0x02,0xF8,0x01,0xE0,0x01,0x80,0x05,0x00,0x01,0x1F,0x01,0x3F,0x01,0x7F,0x01,0xF8,0x02,0xE0,0x03,0xC0,0x02,0xE0,0x01,0xF0,0x01,0x7F,0x01,0x3F,0x01,0x1F,0x01,0x03,0x04,0x00,0x01,0xF8,0x01,0xFE,0x01,0xFF,0x01,0x8F,0x02,0x03,0x05,0x01,0x02,0x03,0x01,0x0F,0x01,0xFF,0x01,0xFE,0x01,0xF8,0x04,0x00,0x01,0x01,0x01,0x07,0x01,0x0F,0x01,0x1F,0x01,0x1E,0x01,0x1C,0x01,0x3C,0x03,0x38,0x01,0x3C,0x01,0x1C,0x01,0x1E,0x01,0x1F,0x01,0x0F,0x01,0x07,0x01,0x03,0x02,0x00, // 8
  998.     0x02,0x00,0x01,0x80,0x01,0xE0,0x01,0xF0,0x01,0xF8,0x01,0x3C,0x06,0x1C,0x01,0x3C,0x01,0xF8,0x01,0xF0,0x01,0xE0,0x01,0xC0,0x05,0x00,0x03,0xFF,0x01,0xC0,0x08,0x00,0x01,0x80,0x03,0xFF,0x01,0xFE,0x05,0x00,0x01,0x01,0x01,0x03,0x01,0x07,0x01,0x0F,0x06,0x0E,0x01,0x07,0x01,0xC3,0x02,0xFF,0x01,0x7F,0x01,0x07,0x07,0x00,0x04,0x38,0x02,0x1C,0x01,0x1E,0x01,0x0E,0x01,0x0F,0x01,0x07,0x01,0x03,0x01,0x01,0x04,0x00 //  9
  999. };
  1000.  
  1001. const uint16_t font_bitmap_offsets[] = {0, 0x54, 0x6e, 0xc6, 0x11e, 0x15a, 0x1a0, 0x1f4, 0x22e, 0x29e};
  1002.  
  1003. void ssd1306_draw_font(uint8_t x, uint8_t y, uint16_t num)
  1004. {
  1005.     size_t tt = 0;
  1006.     uint8_t x_pos = x;
  1007.     uint8_t y_pos = y;
  1008.  
  1009.     uint8_t num_bytes = 0;
  1010.     uint8_t bytes = 0;
  1011.     uint16_t ii = 0;
  1012.     uint16_t ofset = font_bitmap_offsets[num];;
  1013.  
  1014.     for(tt=0; tt<84;)
  1015.     {
  1016.         num_bytes = font_bitmap[ofset++];
  1017.         bytes = font_bitmap[ofset++];
  1018.  
  1019.         for (ii=0; ii<num_bytes; ++ii)
  1020.         {
  1021.             if (x_pos >= (x + FONT_WIDTH))
  1022.             {
  1023.                 x_pos = x;
  1024.                 y_pos++;
  1025.             }
  1026.  
  1027.             ssd1306_write(CMD, Set_Page_Start_Address_CMD + y_pos);        // set row
  1028.             ssd1306_write(CMD, SSD1306_SETLOWCOLUMN | (x_pos & 0xf));      // set lower column address
  1029.             ssd1306_write(CMD, SSD1306_SETHIGHCOLUMN | (x_pos >> 4));      // set higher column address
  1030.  
  1031.             ssd1306_write(DAT, (uint8_t)bytes);
  1032.             tt++;
  1033.             x_pos++;
  1034.         }
  1035.     }
  1036. }
  1037.  
  1038. void draw_temperature(uint8_t x, uint8_t y, uint16_t temp)
  1039. {
  1040.     if (temp == 0)
  1041.     {
  1042.         ssd1306_draw_font(x, y, 0);
  1043.         ssd1306_draw_font(x+FONT_WIDTH, y, 0);
  1044.         ssd1306_draw_font(x+(2*FONT_WIDTH), y, 0);
  1045.     }
  1046.     else if (temp > 0 && temp < 10)
  1047.     {
  1048.         ssd1306_draw_font(x, y, 0);
  1049.         ssd1306_draw_font(x+FONT_WIDTH, y, 0);
  1050.         ssd1306_draw_font(x+(2*FONT_WIDTH), y, temp);
  1051.     }
  1052.     else if (temp >= 10 && temp < 100)
  1053.     {
  1054.         ssd1306_draw_font(x, y, 0);
  1055.         ssd1306_draw_font(x+FONT_WIDTH, y, (temp/10)%10);
  1056.         ssd1306_draw_font(x+(2*FONT_WIDTH), y, temp%10);
  1057.     }
  1058.     else if (temp >= 100 && temp < 1000)
  1059.     {
  1060.         ssd1306_draw_font(x, y, (temp/100)%10);
  1061.         ssd1306_draw_font(x+FONT_WIDTH, y, (temp/10)%10);
  1062.         ssd1306_draw_font(x+(2*FONT_WIDTH), y, temp%10);
  1063.     }
  1064.     else
  1065.     {
  1066.         ssd1306_draw_font(x, y, 9);
  1067.         ssd1306_draw_font(x+FONT_WIDTH, y, 9);
  1068.         ssd1306_draw_font(x+(2*FONT_WIDTH), y, 9);
  1069.     }
  1070. }
  1071.  
  1072. void ssd1306_fill(uint8_t bmp_data)
  1073. {                                                    
  1074.     uint8_t x_pos = 0;
  1075.     uint8_t page = 0;
  1076.  
  1077.     for (page=0; page < y_max; ++page)
  1078.     {
  1079.         ssd1306_write(CMD, (Set_Page_Start_Address_CMD + page));
  1080.         ssd1306_write(CMD, SSD1306_SETLOWCOLUMN);
  1081.         ssd1306_write(CMD, SSD1306_SETHIGHCOLUMN);
  1082.  
  1083.         for (x_pos=0; x_pos < SSD1306_LCDWIDTH; ++x_pos)
  1084.         {
  1085.             ssd1306_write(DAT, bmp_data);
  1086.         }                                                                                  
  1087.     }  
  1088. }
  1089.  
  1090. #define ADS1115_I2C_ADDRESS    (0x48 << 1)
  1091.  
  1092. uint16_t ADS1115_Read(void)
  1093. {
  1094.     uint8_t timeout;
  1095.     uint8_t buffer[2];
  1096.  
  1097.     I2C_Start();
  1098.     I2C_Write(ADS1115_I2C_ADDRESS);
  1099.     I2C_Write(1);  // config register
  1100.     I2C_Write(0b11000101); // start conversion, AIN0 and GND, FSR=2.048, single shot mode
  1101.     I2C_Write(0b10100011); // 250 SPS, Traditional comparator, alert pin active low, nonlatching comparator, disable comparator, alert pin high impedance
  1102.     I2C_Stop();
  1103.  
  1104.     // wait for conversion complete (10ms max)
  1105.     timeout = 100;
  1106.     do {
  1107.         I2C_Start();
  1108.         I2C_Write(ADS1115_I2C_ADDRESS+1);
  1109.         buffer[0] = I2C_Read(1);
  1110.         buffer[1] = I2C_Read(0);
  1111.         I2C_Stop();
  1112.         __delay_us(100);
  1113.     } while (!(buffer[0] & 0x80) && --timeout);
  1114.  
  1115.     // read conversion register
  1116.     I2C_Start();
  1117.     I2C_Write(ADS1115_I2C_ADDRESS);
  1118.     I2C_Write(0x00);    // conversion register is 0
  1119.     I2C_Stop();
  1120.     I2C_Start();
  1121.     I2C_Write(ADS1115_I2C_ADDRESS+1);
  1122.     buffer[0] = I2C_Read(1);
  1123.     buffer[1] = I2C_Read(0);
  1124.     I2C_Stop();
  1125.  
  1126.     return buffer[0] << 8 | buffer[1];
  1127. }
  1128.  
  1129. #define JBC_MAX_TEMP 350
  1130.  
  1131. uint16_t read_temp(void)
  1132. {
  1133.     float temperature;
  1134.  
  1135.     // temperatura = (VOUT - VREF)/(5 mV/ C)
  1136.     // LSB = FSR / 32767;
  1137.     // temperatura = ((advalue * LSB) - VREF) / 0.005
  1138.     temperature = (float)(((ADS1115_Read() * (2.048 / 32767.0)) - 1.24) / 0.005);
  1139.  
  1140.     return (uint16_t)temperature;
  1141. }
  1142.  
  1143. __EEPROM_DATA(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
  1144.  
  1145. void main(void)
  1146. {
  1147.     bool tempset_changed = false;
  1148.     uint16_t temperature = 350; //max temp
  1149.     uint16_t temperature_set = eeprom_read(0) << 8 | eeprom_read(1);
  1150.  
  1151.     // initialize the device
  1152.     SYSTEM_Initialize();
  1153.  
  1154.     // When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
  1155.     // Use the following macros to:
  1156.  
  1157.     // Enable the Global Interrupts
  1158.     INTERRUPT_GlobalInterruptEnable();
  1159.  
  1160.     // Enable the Peripheral Interrupts
  1161.     INTERRUPT_PeripheralInterruptEnable();
  1162.  
  1163.     // Disable the Global Interrupts
  1164.     //INTERRUPT_GlobalInterruptDisable();
  1165.  
  1166.     // Disable the Peripheral Interrupts
  1167.     //INTERRUPT_PeripheralInterruptDisable();
  1168.  
  1169.     I2C_Init(400000);    // initialize I2C bus with clock frequency of 400kHz
  1170.    
  1171.     ssd1306_init();
  1172.     ssd1306_fill(0);
  1173.  
  1174.     draw_temperature(33, 0, temperature_set);
  1175.  
  1176.     while(1)
  1177.     {
  1178.         while(IO_RA4_GetValue() == LOW); // wait zero cross
  1179.         IO_RA5_SetLow();
  1180.  
  1181.         temperature = read_temp();
  1182.         draw_temperature(33, 4, temperature);
  1183.  
  1184.         while(IO_RA0_GetValue() == LOW)
  1185.         {
  1186.             if (temperature_set < JBC_MAX_TEMP)
  1187.             {
  1188.                 temperature_set += 5;
  1189.                 draw_temperature(33, 0, temperature_set);
  1190.                 tempset_changed = true;
  1191.             }
  1192.         }
  1193.  
  1194.         while(IO_RA3_GetValue() == LOW)
  1195.         {
  1196.             if (temperature_set >= 5)
  1197.             {
  1198.                 temperature_set -= 5;
  1199.                 draw_temperature(33, 0, temperature_set);
  1200.                 tempset_changed = true;
  1201.             }
  1202.         }
  1203.  
  1204.         if (tempset_changed)
  1205.         {
  1206.             eeprom_write(0, (temperature_set >> 8) & 0xff);
  1207.             eeprom_write(1, temperature_set & 0xff);
  1208.             tempset_changed = false;
  1209.         }
  1210.  
  1211.         if (temperature < temperature_set)
  1212.         {
  1213.             while(IO_RA4_GetValue() == LOW); // wait zero cross
  1214.             IO_RA5_SetHigh();
  1215.         }
  1216.     }
  1217. }
  1218.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement