Library to control the EM027BS013 ePaper display from Pervasive Display.
Dependents: app_epaper_EM027BS013_LPC1549 lpc4088_ebb_epaper EaEpaper_EM027BS013 app_epaper_EM027BS013 ... more
EPD_hardware_driver.cpp
- Committer:
- embeddedartists
- Date:
- 2014-07-22
- Revision:
- 0:9297e33f50cf
File content as of revision 0:9297e33f50cf:
/** * \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(); }