539 lines
15 KiB
C
539 lines
15 KiB
C
/*##############################################################*/
|
|
/* */
|
|
/* 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 <http://www.gnu.org/licenses/>. */
|
|
/* */
|
|
/* */
|
|
/* Revision History: */
|
|
/* */
|
|
/* Version 1.0 - Initial release */
|
|
/* */
|
|
/* */
|
|
/* */
|
|
/*##############################################################*/
|
|
|
|
#include <bcm2835.h>
|
|
#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 );
|
|
}
|
|
|