/*##############################################################*/ /* */ /* File : RAIO8870.c */ /* */ /* Project : TFT for Raspberry Pi Revision 2 */ /* */ /* Date : 2014-08-14 last update: 2014-08-14 */ /* */ /* Author : Hagen Ploog */ /* Kai Gillmann */ /* Timo Pfander */ /* */ /* IDE : Geany 1.22 */ /* Compiler : gcc (Debian 4.6.3-14+rpi1) 4.6.3 */ /* */ /* Copyright (C) 2013 admatec GmbH */ /* */ /* */ /* Description : */ /* */ /* This file contain several functions to initialize and */ /* control the graphic controller RAIO8870. */ /* */ /* */ /* License: */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify it under the terms of the GNU General */ /* Public License as published by the Free Software */ /* Foundation; either version 3 of the License, or */ /* (at your option) any later version. */ /* */ /* This program is distributed in the hope that it will */ /* be useful, but WITHOUT ANY WARRANTY; without even the */ /* implied warranty of MERCHANTABILITY or */ /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General */ /* Public License for more details. */ /* */ /* You should have received a copy of the GNU General */ /* Public License along with this program; if not, */ /* see . */ /* */ /* */ /* Revision History: */ /* */ /* Version 1.0 - Initial release */ /* */ /* */ /* */ /*##############################################################*/ #include #include "RAIO8870.h" #include "tft.h" uint16_t txc = 0x00; // character x position on screen uint16_t tyc = 0x00; // character y position on screen uint8_t char_higth = 15; // character hight depends on character set #ifdef CM_4K static uint8_t BankNo_WR=0, BankNo_RD=1; #endif struct touch my_touch; uint8_t touch_buffer_full; uint32_t low_pass_x[3], low_pass_y[3]; uint8_t low_pass_pointer; // write command to a register // ---------------------------------------------------------- void RAIO_SetRegister( uint8_t reg, uint8_t value ) { TFT_RegWrite( (uint16_t)reg ); TFT_DataWrite( (uint16_t)value ); } // read data from a register // ---------------------------------------------------------- uint8_t RAIO_GetRegister( uint8_t reg ) { uint8_t value; TFT_RegWrite( (uint16_t)reg ); value = TFT_DataRead(); return ( value ); } // set PWM value for backlight // ---------------------------------------------------------- void RAIO_SetBacklightPWMValue( uint8_t BL_value ) { RAIO_SetRegister( P1CR, 0x88 ); // Enable PWM1 output devider 256 RAIO_SetRegister( P1DCR, BL_value ); // -> BL_vaue = 0 (0% PWM) - 255 (100% PWM) } // initialization of RAIO8870 // ---------------------------------------------------------- void RAIO_init( void ) { static uint8_t PLL_Initial_Flag = 0; // *************** PLL settings (System Clock) if ( !PLL_Initial_Flag ) // wait until PLL is ready { PLL_Initial_Flag = 1; // set Flag to avoid repeated PLL init RAIO_SetRegister( PLLC1, 0x07 ); // set sys_clk bcm2835_delayMicroseconds( 200 ); RAIO_SetRegister( PLLC2, 0x03 ); // set sys_clk bcm2835_delayMicroseconds( 200 ); RAIO_SetRegister( PWRR, 0x01 ); // Raio software reset ( bit 0 ) set RAIO_SetRegister( PWRR, 0x00 ); // Raio software reset ( bit 0 ) set to 0 delay( 100 ); // *************** color modes (color depths) #ifdef CM_65K // System Configuration Register RAIO_SetRegister( SYSR, 0x0A ); // digital TFT // parallel data out // no external memory // 8bit memory data bus // 16bpp 65K color // 16bit MCU-interface (data) RAIO_SetRegister( DPCR, 0x00 ); // one layer #elif defined(CM_4K) // System Configuration Register RAIO_SetRegister( SYSR, 0x06 ); // digital TFT // parallel data out // no external memory // 8bit memory data bus // 12bpp 4K color // 16bit MCU-interface (data) RAIO_SetRegister( DPCR, 0x80 ); // two layers RAIO_SetRegister( MWCR1, BankNo_WR ); RAIO_SetRegister( LTPR0, BankNo_RD ); #else #error "color_mode not defined" #endif } // *************** horizontal settings // 0x27+1 * 8 = 320 pixel RAIO_SetRegister( HDWR , (DISPLAY_WIDTH / 8) - 1 ); // Horizontal Non-Display Period Fine Tuning RAIO_SetRegister( HNDFTR, 0x02 ); // HNDR , Horizontal Non-Display Period Bit[4:0] // Horizontal Non-Display Period (pixels) = (HNDR + 1)*8 RAIO_SetRegister( HNDR, 0x03 ); // HSTR , HSYNC Start Position[4:0], HSYNC Start Position(PCLK) = (HSTR + 1)*8 0x02 RAIO_SetRegister( HSTR, 0x04 ); // HPWR , HSYNC Polarity ,The period width of HSYNC. // 1xxxxxxx activ high 0xxxxxxx activ low // HSYNC Width [4:0] HSYNC Pulse width // (PCLK) = (HPWR + 1)*8 RAIO_SetRegister( HPWR, 0x03 ); // ********************* vertical settings // 0x0EF +1 = 240 pixel RAIO_SetRegister( VDHR0 , ( (DISPLAY_HEIGHT-1) & 0xFF ) ); RAIO_SetRegister( VDHR1 , ( (DISPLAY_HEIGHT-1) >> 8) ); // VNDR0 , Vertical Non-Display Period Bit [7:0] // Vertical Non-Display area = (VNDR + 1) // VNDR1 , Vertical Non-Display Period Bit [8] // Vertical Non-Display area = (VNDR + 1) RAIO_SetRegister( VNDR0, 0x10 ); RAIO_SetRegister( VNDR1, 0x00 ); // VPWR , VSYNC Polarity ,VSYNC Pulse Width[6:0] // VSYNC , Pulse Width(PCLK) = (VPWR + 1) RAIO_SetRegister( VPWR, 0x00 ); // *************** miscellaneous settings // active Window Active_Window( 0, DISPLAY_WIDTH-1, 0, DISPLAY_HEIGHT-1 ); // PCLK fetch data on rising edge RAIO_SetRegister( PCLK, 0x00 ); // Backlight dimming RAIO_SetBacklightPWMValue(50); // memory clear with background color Text_Background_Color( COLOR_WHITE ); RAIO_SetRegister( MCLR, 0x81 ); TFT_wait_for_raio(); RAIO_SetRegister( IODR, 0x07 ); RAIO_SetRegister( PWRR, 0x80 ); #ifdef touch_available // Touch Panel enable // wait 4096 system clocks period // ADC clock = system clock / 16 RAIO_SetRegister( TPCR0, 0xB7 ); // 4wire, auto mode, internal vref enabled // debounce enabled, idle mode RAIO_SetRegister( TPCR1, 0x84 ); // enable touch interrupt RAIO_SetRegister( INTC, 0x40 ); // init touch structure my_touch.state = no_touch; // init touch values touch_buffer_full = 0; low_pass_pointer = 0; #endif } #ifdef touch_available // get touch coords // ---------------------------------------------------------- int32_t RAIO_gettouch() { uint8_t mask; uint8_t dummy_tp; uint32_t touch_x, touch_y; mask= RAIO_GetRegister( INTC ); if ( mask & 0x04 ) { // read the data for x and y touch_x = RAIO_GetRegister ( TPXH ); touch_y = RAIO_GetRegister ( TPYH ); // fill low pass filter with the new values low_pass_x[ low_pass_pointer ] = touch_x; low_pass_y[ low_pass_pointer ] = touch_y; low_pass_pointer++; if (low_pass_pointer == debounce_buffer_size) { low_pass_pointer = 0; touch_buffer_full = 1; } // calculate the average my_touch.touch_x = (low_pass_x[0] + low_pass_x[1] + low_pass_x[2] + low_pass_x[3] ) >> 2; my_touch.touch_y = (low_pass_y[0] + low_pass_y[1] + low_pass_y[2] + low_pass_y[3] ) >> 2; if (touch_buffer_full == 1) { switch (my_touch.state) { case down : my_touch.state= pressed; break; case no_touch : my_touch.state = down; break; default : break; } } // clear touch irq mask &= 0xf4 ; RAIO_SetRegister( INTC, mask ); return ( 1 ); } else { switch (my_touch.state) { case up : my_touch.state = no_touch; break; case pressed: my_touch.state = up; break; default : break; } low_pass_pointer = 0; touch_buffer_full = 0; return ( 0 ); } } #endif // set coordinates for active window // ---------------------------------------------------------- void Active_Window( uint16_t XL, uint16_t XR , uint16_t YT, uint16_t YB ) { union my_union number; //setting active window X number.value = XL; RAIO_SetRegister( HSAW0, number.split.low ); RAIO_SetRegister( HSAW1, number.split.high ); number.value = XR; RAIO_SetRegister( HEAW0, number.split.low ); RAIO_SetRegister( HEAW1, number.split.high ); //setting active window Y number.value = YT; RAIO_SetRegister( VSAW0, number.split.low ); RAIO_SetRegister( VSAW1, number.split.high ); number.value = YB; RAIO_SetRegister( VEAW0, number.split.low ); RAIO_SetRegister( VEAW1, number.split.high ); } // set cursor // ---------------------------------------------------------- void RAIO_set_cursor( uint16_t pos_x ,uint16_t pos_y ) { union my_union number; number.value = pos_x; RAIO_SetRegister( CURH0, number.split.low ); RAIO_SetRegister( CURH1, number.split.high ); number.value = pos_y; RAIO_SetRegister( CURV0, number.split.low ); RAIO_SetRegister( CURV1, number.split.high ); } // show the BMP picture on the TFT screen // ---------------------------------------------------------- void RAIO_Write_Picture( uint16_t *data, uint32_t count ) { TFT_RegWrite( MRWC ); TFT_DataMultiWrite( data, count); #ifdef CM_4K if ( BankNo_WR==0 ) { BankNo_WR=1; BankNo_RD=0; } else { BankNo_WR=0; BankNo_RD=1; } RAIO_SetRegister( MWCR1, BankNo_WR ); RAIO_SetRegister( LTPR0, BankNo_RD ); #endif } // set mode for BET (Block Transfer Engine) // ---------------------------------------------------------- void BTE_mode( uint8_t bte_operation, uint8_t rop_function ) { RAIO_SetRegister( BECR1, bte_operation | (rop_function<<4) ); } // set color // ---------------------------------------------------------- void Text_Background_Color( uint8_t color ) { RAIO_SetRegister( TBCR, color ); } void Text_Foreground_Color( uint8_t color) { RAIO_SetRegister( TFCR, color); } // clear screen // ---------------------------------------------------------- void RAIO_clear_screen( void ) { // for more informations see RA8870 specification page 40 // // | Bit | Function // |-----|------------------------------------------------- // | 7 | 0 = stop clear 1 = start clear // | 6 | 0 = fullwindow 1 = activewindow // | 5-1 | NA // | 0 | 0 = Memory clear with BTE background color 1 = Memory clear with font background color // // Reg 0x43 define font background color ( RRRGGGBB ) // Reg 0x60, 0x61, 0x62 define BTE background color ( BGCR0=red[4:0], BGCR1=green[5:0], BGCR2=blue[4:0] ) RAIO_SetRegister( MCLR , 0x81 ); TFT_wait_for_raio(); } // print text // ---------------------------------------------------------- void RAIO_print_text( uint16_t pos_x, uint16_t pos_y, unsigned char *str, uint8_t BG_color, uint8_t FG_color ) { // set cursor RAIO_set_cursor( pos_x, pos_y ); // set color Text_Background_Color( BG_color ); Text_Foreground_Color( FG_color ); // set text mode RAIO_SetRegister( MWCR0, 0x80 ); // write text to display TFT_RegWrite( MRWC ); while ( *str != '\0' ) { TFT_DataWrite( *str ); ++str; TFT_wait_for_raio(); } TFT_wait_for_raio(); // set graphic mode RAIO_SetRegister( MWCR0, 0x00 ); } // set font size // ---------------------------------------------------------- void RAIO_SetFontSizeFactor( uint8_t size ) { size = (size & 0x0f); RAIO_SetRegister ( FNCR1, size ); } // set coordinates for drawing line and square // ---------------------------------------------------------- void Set_Geometric_Coordinate(uint16_t X1, uint16_t Y1 ,uint16_t X2 ,uint16_t Y2 ) { union my_union number; number.value = X1; RAIO_SetRegister( DLHSR0, number.split.low ); RAIO_SetRegister( DLHSR1, number.split.high ); number.value = Y1; RAIO_SetRegister( DLVSR0, number.split.low ); RAIO_SetRegister( DLVSR1, number.split.high ); number.value = X2; RAIO_SetRegister( DLHER0, number.split.low ); RAIO_SetRegister( DLHER1, number.split.high ); number.value = Y2; RAIO_SetRegister( DLVER0, number.split.low ); RAIO_SetRegister( DLVER1, number.split.high ); } // set coordinates for drawing circle // ---------------------------------------------------------- void Set_Geometric_Coordinate_circle (uint16_t X1, uint16_t Y1 ,uint8_t rad ) { union my_union number; number.value = X1; RAIO_SetRegister( DCHR0, number.split.low ); RAIO_SetRegister( DCHR1, number.split.high ); number.value = Y1; RAIO_SetRegister( DCVR0, number.split.low ); RAIO_SetRegister( DCVR1, number.split.high ); RAIO_SetRegister( DCRR, rad ); } // set draw mode // ---------------------------------------------------------- void RAIO_StartDrawing( int16_t whattodraw ) { switch( whattodraw ) // -> see DRAW_MODES { case CIRCLE_NONFILL: {RAIO_SetRegister( DCR, 0x40 ); break;} case CIRCLE_FILL: {RAIO_SetRegister( DCR, 0x60 ); break;} case SQUARE_NONFILL: {RAIO_SetRegister( DCR, 0x90 ); break;} case SQUARE_FILL: {RAIO_SetRegister( DCR, 0xB0 ); break;} case LINE: {RAIO_SetRegister( DCR, 0x80 ); break;} default: break; } TFT_wait_for_raio(); } // draw some basic geometrical forms // ---------------------------------------------------------- void Draw_Line( uint16_t X1, uint16_t Y1 ,uint16_t X2 ,uint16_t Y2 ) { Set_Geometric_Coordinate( X1, Y1, X2, Y2 ); RAIO_StartDrawing( LINE ); } void Draw_Square( uint16_t X1, uint16_t Y1 ,uint16_t X2 ,uint16_t Y2 ) { Set_Geometric_Coordinate( X1, Y1, X2, Y2 ); RAIO_StartDrawing( SQUARE_NONFILL ); } void Draw_Circle( uint16_t X1, uint16_t Y1 ,uint8_t rad ) { Set_Geometric_Coordinate_circle ( X1, Y1, rad ); RAIO_StartDrawing( CIRCLE_NONFILL ); }