Library to control the EM027BS013 ePaper display from Pervasive Display.
Dependents: app_epaper_EM027BS013_LPC1549 lpc4088_ebb_epaper EaEpaper_EM027BS013 app_epaper_EM027BS013 ... more
Diff: EPD_hardware_driver.cpp
- Revision:
- 0:9297e33f50cf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EPD_hardware_driver.cpp Tue Jul 22 11:59:06 2014 +0000 @@ -0,0 +1,485 @@ +/** + * \file + * + * \brief The initialization and configuration of COG hardware driver + * + * Copyright (c) 2012-2014 Pervasive Displays Inc. All rights reserved. + * + * Authors: Pervasive Displays Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//#include <math.h> +#include "EPD_hardware_driver.h" + +static uint16_t EPD_Counter; +static uint8_t spi_flag = FALSE; + +#include "mbed.h" +#include "LM75B.h" +static Ticker systemTicker; +static SPI* expSPI = NULL; +static LM75B* expLM75B = NULL; +void SysTick_Handler(void); + +extern PinName SEC03; +extern PinName SEC04; +extern PinName SEC05; +extern PinName SEC09; +extern PinName SEC10; + + +/** + * \brief Set up EPD Timer for 1 mSec interrupts + * + * \note + * desired value: 1mSec + * actual value: 1.000mSec + */ +static void initialize_EPD_timer(void) { + //------------------Timer A1---------------------------------------- + //set up Timer_A CCR1 as master timer using ACLK +// TA0CCTL2 &= ~(CCIFG | CCIE); // reset CCIFG Interrupt Flag +// TA0CTL = TASSEL_2 + MC_0 + TACLR + ID_3; +// TA0CCTL2 = OUTMOD_4; + EPD_Counter = 0; +} + +/** + * \brief Start Timer + */ +void start_EPD_timer(void) { + initialize_EPD_timer(); +// TA0R = 0; +// TA0CCR0 = 990 * 2; // 1ms +// TA0CCTL2 |= CCIE; +// TA0CTL |= MC_1; + EPD_Counter = 0; + systemTicker.attach_us(&SysTick_Handler, 1000); +} + +/** + * \brief Stop Timer + */ +void stop_EPD_timer(void) { +// TA0CCTL2 &= ~CCIE; +// TA0CTL &= ~MC_1; + systemTicker.detach(); +} + +/** + * \brief Get current Timer after starting a new one + */ +uint32_t get_current_time_tick(void) { + return EPD_Counter; +} +/** + * \brief Set current Timer after starting a new one + */ +void set_current_time_tick(uint32_t count) { + EPD_Counter=count; +} +/** + * \brief Interrupt Service Routine for system tick counter + */ +void SysTick_Handler(void) { + EPD_Counter++; +} + +///** +// * \brief Interrupt Service Routine for Timer A0 +// */ +//#pragma vector=TIMER0_A1_VECTOR +//__interrupt void Timer_A0(void) { +// switch (__even_in_range(TA0IV, 10)) { +// case 2: +// //LPM3_EXIT; +// break; + +// case 4: +// EPD_Counter++; +// LPM3_EXIT; +// break; +// } + +//} + +/** + * \brief Delay mini-seconds + * \param ms The number of mini-seconds + */ +void delay_ms(unsigned int ms) { +// while (ms--) { +// __delay_cycles(SMCLK_FREQ / 1000); +// } + wait_ms(ms); +} + +/** + * \brief Delay mini-seconds + * \param ms The number of mini-seconds + */ +void sys_delay_ms(unsigned int ms) { +// delay_ms(ms); + wait_ms(ms); +} + +static void Wait_10us(void) { +// __delay_cycles(SMCLK_FREQ / 100000); + wait_us(10); +} + +//****************************************************************** +//* PWM Configuration/Control //PWM output : PD3 +//****************************************************************** + +/** + * \brief The PWM signal starts toggling + */ +void PWM_start_toggle(void) { + +} + +/** + * \brief The PWM signal stops toggling. + */ +void PWM_stop_toggle(void) { + +} + +/** + * \brief PWM toggling. + * + * \param ms The interval of PWM toggling (mini seconds) + */ +void PWM_run(uint16_t ms) { +// start_EPD_timer(); +// do { +// EPD_pwm_high(); +// __delay_cycles(30); +// EPD_pwm_low(); +// __delay_cycles(30); +// } while (get_current_time_tick() < ms); //wait Delay Time +// stop_EPD_timer(); + mbed_die(); +} + +//****************************************************************** +//* SPI Configuration +//****************************************************************** + +/** + * \brief Configure SPI + */ +void epd_spi_init(void) { + if (spi_flag) + return; + spi_flag = TRUE; +// //config i/o +// config_gpio_dir_o(SPICLK_PORT, SPICLK_PIN); +// config_gpio_dir_o(SPIMOSI_PORT, SPIMOSI_PIN); +// config_gpio_dir_i(SPIMISO_PORT, SPIMISO_PIN); + +// BITSET(SPISEL, SPICLK_PIN + SPIMOSI_PIN + SPIMISO_PIN); +// BITSET(SPISEL2, SPICLK_PIN + SPIMOSI_PIN + SPIMISO_PIN); +// //comfig SPI +// SPICTL0 = UCCKPH | UCMST | UCSYNC | UCMSB; +// SPICTL1 = UCSSEL_2 + UCSWRST; +// SPIBR0 = 2; //16MHz/2=8MHz +// SPIBR1 = 0; + +// BITSET(REN (SPIMISO_PORT), SPIMISO_PIN); +// BITCLR(SPICTL1, UCSWRST); + + expSPI = new SPI(SEC04, SEC05, SEC03); // mosi, miso, sclk + expSPI->frequency(COG_SPI_baudrate); +} + +/** + * \brief Initialize SPI + */ +void epd_spi_attach(void) { + EPD_flash_cs_high(); + EPD_cs_high(); + epd_spi_init(); +} + +/** + * \brief Disable SPI and change to GPIO + */ +void epd_spi_detach(void) { +// BITCLR(SPISEL, SPICLK_PIN + SPIMOSI_PIN + SPIMISO_PIN); +// BITCLR(SPISEL2, SPICLK_PIN + SPIMOSI_PIN + SPIMISO_PIN); +// //config_gpio_dir_o(SPICLK_PORT,SPICLK_PIN); +// //config_gpio_dir_o(SPIMOSI_PORT,SPIMOSI_PIN); +// //config_gpio_dir_o(SPIMISO_PORT,SPIMISO_PIN); +// SPIMISO_low(); +// SPIMOSI_low(); +// SPICLK_low(); + if (expSPI != NULL) { + delete expSPI; + expSPI = NULL; + } + spi_flag = FALSE; +} + +/** + * \brief SPI synchronous write + */ +void epd_spi_write(unsigned char Data) { +// SPITXBUF = Data; +// while (!(SPIIFG & SPITXIFG)) +// ; + expSPI->write(Data); +} + +/** + * \brief SPI synchronous read + */ +uint8_t epd_spi_read(unsigned char RDATA) { +// SPITXBUF = RDATA; +// while ((SPISTAT & UCBUSY)) +// ; +// RDATA = SPIRXBUF; +// return RDATA; + return expSPI->write(RDATA) & 0xff; +} + +/** + * \brief Send data to SPI with time out feature + * + * \param data The data to be sent out + */ +uint8_t epd_spi_write_ex(unsigned char Data) { +// uint8_t cnt = 200; +// uint8_t flag = 1; +// SPITXBUF = Data; +// while (!(SPIIFG & SPITXIFG)) { +// if ((cnt--) == 0) { +// flag = 0; +// break; +// } +// } +// return flag; + + // Not used + mbed_die(); + return 0; +} + +#if (defined COG_V230_G2) +/** +* \brief SPI command +* +* \param register_index The Register Index as SPI Data to COG +* \param register_data The Register Data for sending command data to COG +* \return the SPI read value +*/ +uint8_t SPI_R(uint8_t Register, uint8_t Data) { + uint8_t result; + EPD_cs_low (); + epd_spi_write (0x70); // header of Register Index + epd_spi_write (Register); + + EPD_cs_high (); + Wait_10us (); + EPD_cs_low (); + + epd_spi_write (0x73); // header of Register Data of read command + result=epd_spi_read (Data); + + EPD_cs_high (); + + return result; +} +#endif + +/** +* \brief SPI command if register data is larger than two bytes +* +* \param register_index The Register Index as SPI command to COG +* \param register_data The Register Data for sending command data to COG +* \param length The number of bytes of Register Data which depends on which +* Register Index is selected. +*/ +void epd_spi_send (unsigned char register_index, unsigned char *register_data, + unsigned length) { + EPD_cs_low (); + epd_spi_write (0x70); // header of Register Index + epd_spi_write (register_index); + + EPD_cs_high (); + Wait_10us (); + EPD_cs_low (); + + epd_spi_write (0x72); // header of Register Data of write command + while(length--) { + epd_spi_write (*register_data++); + } + EPD_cs_high (); +} + +/** +* \brief SPI command +* +* \param register_index The Register Index as SPI command to COG +* \param register_data The Register Data for sending command data to COG +*/ +void epd_spi_send_byte (uint8_t register_index, uint8_t register_data) { + EPD_cs_low (); + epd_spi_write (0x70); // header of Register Index + epd_spi_write (register_index); + + EPD_cs_high (); + Wait_10us (); + EPD_cs_low (); + epd_spi_write (0x72); // header of Register Data + epd_spi_write (register_data); + EPD_cs_high (); +} + +//****************************************************************** +//* Temperature sensor Configuration +//****************************************************************** +#ifdef __Internal_Temperature_Sensor +// ADC10 interrupt service routine +#pragma vector=ADC10_VECTOR +__interrupt void ADC10_ISR(void) { + __bic_SR_register_on_exit(CPUOFF); + // Clear CPUOFF bit from 0(SR) +} +/** + * \brief Get temperature value from ADC + * + * \return the Celsius temperature + */ +int16_t get_temperature(void) { + const uint8_t DegCOffset=0; + long temp; + float IntDegC; + + ADC10CTL1 = INCH_10 + ADC10DIV_3; // Temp Sensor ADC10CLK/4 + ADC10CTL0 = SREF_1 + ADC10SHT_3 + REFON + ADC10ON+ADC10IE; + ADC10CTL0 |= ENC + ADC10SC;// Sampling and conversion start + __bis_SR_register(CPUOFF + GIE);// LPM0, ADC10_ISR will force exit + // oC = ((A10/1024)*1500mV)-986mV)*1/3.55mV = A10*423/1024 - 278 + temp = ADC10MEM; + + ADC10CTL0 |= ENC + ADC10SC;// Sampling and conversion start + __bis_SR_register(CPUOFF + GIE);// LPM0, ADC10_ISR will force exit + temp = ADC10MEM; + ADC10CTL0 |= ENC + ADC10SC;// Sampling and conversion start + __bis_SR_register(CPUOFF + GIE);// LPM0, ADC10_ISR will force exit + temp += ADC10MEM; + temp=temp/2; + + IntDegC =(long)((long)(temp*423)/1024)-(278+DegCOffset);//(long)((long)(temp - 673) * 423) / 1024; + + __no_operation();// SET BREAKPOINT HERE + + return (int8_t) IntDegC; +} +#elif defined __External_Temperature_Sensor + +/** + * \brief Get temperature value from ADC + * + * \return the Celsius temperature + */ +int16_t get_temperature(void) { +// float IntDegC; +// const uint8_t DegCOffset = 2; +// long temp; +// ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start +// __bis_SR_register(CPUOFF + GIE); +// // LPM0, ADC10_ISR will force exit +// temp = ADC10MEM; + +// ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start +// __bis_SR_register(CPUOFF + GIE); +// // LPM0, ADC10_ISR will force exit +// temp = ADC10MEM; +// ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start +// __bis_SR_register(CPUOFF + GIE); +// // LPM0, ADC10_ISR will force exit +// temp = ADC10MEM; +// ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start +// __bis_SR_register(CPUOFF + GIE); +// // LPM0, ADC10_ISR will force exit +// temp = ADC10MEM; + +// //org +// /* +// temp = (ADC10MEM*5)/2; +// voltage = (float)((float)temp*2.5)/1024.0; //(2.5/1024)*ADC=Mcu voltage,Temperature voltage=Mcu voltage*2 +// IntDegC=100.0- (((voltage*1000)/10.77)-111.3); //100-((Temperature voltage-1.199)*1000)/10.77=IntDegC +// __no_operation(); // SET BREAKPOINT HERE +// */ +// //adj +// // IntDegC=(203-DegCOffset)-((long)((7*temp)/128)+(temp/2)); +// IntDegC = (201 - DegCOffset) - ((long) ((5 * temp) / 128) + (temp / 2)); +// return (int16_t) IntDegC; + + float f = *expLM75B; + return (int)f; +} + +#endif + +/** + * \brief Initialize the temperature sensor + */ +void initialize_temperature(void) { +#ifdef __External_Temperature_Sensor + + //Create an LM75B object at 0x92/0x93 (ADDRESS_1) + expLM75B = new LM75B(SEC10, SEC09, LM75B::ADDRESS_1); // Requires JP8 and JP9 in 1-2 position to avoid interference from LM75 on ARM University BB + + //Try to open the LM75B + if (!expLM75B->open()) { +// mbed_die(); + } +// ADC10CTL0 = SREF_1 + ADC10SHT_3 + ADC10ON + ADC10IE + REFON + REF2_5V; // ADC10ON, interrupt enabled +// ADC10CTL1 = INCH_4 + ADC10DIV_3; // input A1.4 + +#endif +} + +/** + * \brief Initialize the EPD hardware setting + */ +void EPD_display_hardware_init(void) { + EPD_initialize_gpio(); + EPD_Vcc_turn_off(); + epd_spi_init(); + initialize_temperature(); + EPD_cs_low(); + EPD_pwm_low(); + EPD_rst_low(); + EPD_discharge_low(); + EPD_border_low(); + //initialize_EPD_timer(); +} +