Display - cleanup and better "example"
* Moved test pattern to main program * Use the touchscreen to affect display brightness
This commit is contained in:
parent
f8a5204ded
commit
299adc5db9
6 changed files with 350 additions and 168 deletions
|
@ -1,6 +1,7 @@
|
|||
PROJECT = BitBangDisplay
|
||||
PRJ_C_SRC = main.c \
|
||||
ssd1963.c
|
||||
ssd1963.c \
|
||||
xpt2046.c
|
||||
|
||||
##############################################################################
|
||||
# Build global options
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "hal.h"
|
||||
|
||||
#include "ssd1963.h"
|
||||
#include "xpt2046.h"
|
||||
|
||||
// This is called when the board boots up with the user button pressed. The
|
||||
// idea is to enter this mode if the wrong SPI device has been used and flashing
|
||||
|
@ -16,8 +17,88 @@ static void lockdown( void )
|
|||
}
|
||||
|
||||
|
||||
void display_off( void );
|
||||
void display_test_pattern( u16 start_mask );
|
||||
static void displayTestPattern( u16 start_mask )
|
||||
{
|
||||
_ssd1963_clear_cs;
|
||||
ssd1963StartWriting( 0 , 0 );
|
||||
int i;
|
||||
for ( i = 0 ; i < SSD1963_SCR_HEIGHT ; i ++ ) {
|
||||
u16 j , c = start_mask;
|
||||
for ( j = 0 ; j < SSD1963_SCR_WIDTH ; j ++ ) {
|
||||
if ( ( j & 7 ) == 7 ) {
|
||||
c >>= 1;
|
||||
if ( !c ) {
|
||||
c = 0x8000;
|
||||
}
|
||||
}
|
||||
ssd1963WriteData( c );
|
||||
}
|
||||
}
|
||||
_ssd1963_set_cs;
|
||||
}
|
||||
|
||||
|
||||
static int tryReading;
|
||||
|
||||
static void onTouchscreenIRQ( EXTDriver * driver __attribute__((unused)) ,
|
||||
expchannel_t channel __attribute__((unused)) )
|
||||
{
|
||||
tryReading = TRUE;
|
||||
}
|
||||
|
||||
|
||||
#define PORT(P) \
|
||||
case (int) GPIO##P : \
|
||||
port = EXT_MODE_GPIO##P; \
|
||||
break;
|
||||
|
||||
static void initIRQs( void )
|
||||
{
|
||||
EXTConfig config;
|
||||
u32 i;
|
||||
|
||||
for ( i = 0 ; i < EXT_MAX_CHANNELS ; i ++ ) {
|
||||
if ( i == XPT2046_IRQ_PAD ) {
|
||||
int port;
|
||||
switch ( (int) XPT2046_IRQ_PORT ) {
|
||||
default: PORT(A); PORT(B);
|
||||
PORT(C); PORT(D); PORT(E);
|
||||
PORT(F); PORT(G); PORT(H);
|
||||
}
|
||||
config.channels[ i ].mode = EXT_CH_MODE_FALLING_EDGE
|
||||
| EXT_CH_MODE_AUTOSTART | port;
|
||||
config.channels[ i ].cb = &onTouchscreenIRQ;
|
||||
} else {
|
||||
config.channels[ i ].mode = EXT_CH_MODE_DISABLED;
|
||||
config.channels[ i ].cb = NULL;
|
||||
}
|
||||
}
|
||||
extStart( &EXTD1 , &config );
|
||||
}
|
||||
|
||||
|
||||
static void checkTouchScreen( void )
|
||||
{
|
||||
int x , y;
|
||||
if ( ! xpt2046GetAverageCoordinates( &x , &y , 3 ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
x >>= 8;
|
||||
|
||||
_ssd1963_clear_cs;
|
||||
ssd1963WriteCommand( SSD1963_CMD_SET_POST_PROC );
|
||||
ssd1963WriteData( 0x40 );
|
||||
ssd1963WriteData( x );
|
||||
ssd1963WriteData( 0x40 );
|
||||
if ( y > 2048 ) {
|
||||
ssd1963WriteData( 0 );
|
||||
} else {
|
||||
ssd1963WriteData( 1 );
|
||||
}
|
||||
_ssd1963_set_cs;
|
||||
}
|
||||
|
||||
|
||||
int main( void )
|
||||
{
|
||||
|
@ -27,14 +108,18 @@ int main( void )
|
|||
lockdown( );
|
||||
}
|
||||
|
||||
xpt2046Init( );
|
||||
initIRQs();
|
||||
ssd1963Init( );
|
||||
|
||||
int i = 0;
|
||||
while (TRUE) {
|
||||
display_test_pattern( 1 << i );
|
||||
displayTestPattern( 1 << i );
|
||||
chThdSleep(100);
|
||||
i = ( i + 1 ) % 16;
|
||||
if ( palReadPad( GPIOA , GPIOA_BUTTON ) ) {
|
||||
display_off( );
|
||||
if ( tryReading ) {
|
||||
checkTouchScreen( );
|
||||
tryReading = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,66 +4,43 @@
|
|||
#include "ssd1963.h"
|
||||
|
||||
|
||||
#define _command 0x40
|
||||
#define _delay 0x80
|
||||
#define _ndata(x) ( (u8)( (x) & 0x3f) )
|
||||
|
||||
static const u8 _ssd1963_reset_sequence[ ] = {
|
||||
/*
|
||||
* PLL configuration
|
||||
* -----------------
|
||||
*
|
||||
* PLL = input * ( P1 + 1 ) / ( P2 + 1 )
|
||||
* (P1 : 8 bits ; P2 : 4 bits; P3 : junk)
|
||||
*
|
||||
* 1/ The ITDB02-4.3 board has a 12MHz crystal (which contradicts the
|
||||
* SSD1963 datasheet - wtf?).
|
||||
* 2/ The SSD1963 must be clocked at *at most* 110MHz.
|
||||
* 3/ Also, 250MHz < input * ( P1 + 1 ) < 800MHz
|
||||
* 4/ The STM32F4 can communicate at 50MHz.
|
||||
* 5/ The SSD1963 accepts PLL/2 accesses per second.
|
||||
*
|
||||
* 100MHz = 12MHz * ( P1 + 1 ) / ( P2 + 1 )
|
||||
* => P1 = 49, P2 = 5
|
||||
* 100MHz = 10MHz * ( P1 + 1 ) / ( P2 + 1 )
|
||||
* => P1 = 19, P2 = 1
|
||||
*/
|
||||
_command | _ndata(3) ,
|
||||
// PLL configuration
|
||||
SSD1963_COMMAND | SSD1963_DATA(3) ,
|
||||
SSD1963_CMD_SET_PLL_MN ,
|
||||
0x31 , 0x05 , 0x04 ,
|
||||
// 0x1e , 0x02 , 0x04 ,
|
||||
0x1e , 0x02 , 0x04 ,
|
||||
|
||||
// Enable PLL and wait until it's stable
|
||||
_command | _delay | _ndata(1) ,
|
||||
SSD1963_COMMAND | SSD1963_DELAY | SSD1963_DATA(1) ,
|
||||
SSD1963_CMD_SET_PLL , 1 ,
|
||||
1 ,
|
||||
|
||||
// Fully enable PLL
|
||||
_command | _ndata(1) ,
|
||||
SSD1963_COMMAND | SSD1963_DATA(1) ,
|
||||
SSD1963_CMD_SET_PLL , 3 ,
|
||||
};
|
||||
|
||||
|
||||
static const u8 _ssd1963_init_sequence[ ] = {
|
||||
// Software reset
|
||||
_command | _delay ,
|
||||
SSD1963_COMMAND | SSD1963_DELAY ,
|
||||
SSD1963_CMD_SOFT_RESET ,
|
||||
5 ,
|
||||
|
||||
/* Pixel clock: screw finesse, crank that up to the max */
|
||||
_command | _ndata( 3 ) | _delay ,
|
||||
// Pixel clock: screw finesse, crank that up to the max
|
||||
SSD1963_COMMAND | SSD1963_DATA( 3 ) | SSD1963_DELAY ,
|
||||
SSD1963_CMD_SET_LSHIFT_FREQ ,
|
||||
0x07 , 0xff , 0xff ,
|
||||
15 ,
|
||||
|
||||
// Use 565 RGB format
|
||||
_command | _delay | _ndata(1) ,
|
||||
SSD1963_COMMAND | SSD1963_DELAY | SSD1963_DATA(1) ,
|
||||
SSD1963_CMD_SET_PIXEL_FORMAT ,
|
||||
0x03 ,
|
||||
5 ,
|
||||
|
||||
// Setup LCD panel
|
||||
_command | _ndata( 7 ) ,
|
||||
SSD1963_COMMAND | SSD1963_DATA( 7 ) ,
|
||||
SSD1963_CMD_SET_LCD_MODE ,
|
||||
0x20 , // Data width 24-bit, FRC and dithering disabled
|
||||
// Data latch on falling edge
|
||||
|
@ -78,7 +55,7 @@ static const u8 _ssd1963_init_sequence[ ] = {
|
|||
( ( SSD1963_SCR_HEIGHT - 1 ) & 0xff ) ,
|
||||
0x00 , // Ignored (serial interface)
|
||||
|
||||
_command | _ndata( 8 ) ,
|
||||
SSD1963_COMMAND | SSD1963_DATA( 8 ) ,
|
||||
SSD1963_CMD_SET_HORI_PERIOD ,
|
||||
0x02 , 0x13 , // Total period (PCLK)
|
||||
0x00 , 0x08 , // Non-display period
|
||||
|
@ -86,86 +63,35 @@ static const u8 _ssd1963_init_sequence[ ] = {
|
|||
0x00 , 0x02 , // Start location (PCLK)
|
||||
0x00 , // Ignored (serial interfaces)
|
||||
|
||||
_command | _ndata( 7 ) ,
|
||||
SSD1963_COMMAND | SSD1963_DATA( 7 ) ,
|
||||
SSD1963_CMD_SET_VERT_PERIOD ,
|
||||
0x01 , 0x20 , // Vertical total period
|
||||
0x00 , 0x04 , // Non-display period
|
||||
0x0c , // Sync pulse width
|
||||
0x00 , 0x02 , // Start location
|
||||
|
||||
_command | _ndata(1) ,
|
||||
0x36 ,
|
||||
0x00 ,
|
||||
SSD1963_COMMAND | SSD1963_DATA(1) ,
|
||||
SSD1963_CMD_SET_ADDRESS_MODE ,
|
||||
0x00 , // Top to bottom, left to right, no reversing,
|
||||
// RGB framebuffer, LCD l-to-r refresh, no
|
||||
// flipping
|
||||
|
||||
_command ,
|
||||
// TE signal is not connected on the ITDB02-4.3
|
||||
SSD1963_COMMAND ,
|
||||
SSD1963_CMD_SET_TEAR_OFF ,
|
||||
|
||||
// Set standard gamma curve
|
||||
SSD1963_COMMAND | SSD1963_DATA(1) ,
|
||||
SSD1963_CMD_SET_GAMMA_CURVE ,
|
||||
1 ,
|
||||
|
||||
// Enable display
|
||||
SSD1963_COMMAND ,
|
||||
SSD1963_CMD_SET_DISPLAY_ON ,
|
||||
|
||||
_command | _ndata(6) ,
|
||||
SSD1963_CMD_SET_PWM_CONF ,
|
||||
0x06 , 0xf0 , 0x01 , 0xf0 , 0 , 0 ,
|
||||
|
||||
_command | _ndata(1) ,
|
||||
0xd0 ,
|
||||
0x0d ,
|
||||
|
||||
_command | _ndata(1) , SSD1963_CMD_SET_GAMMA_CURVE, 1 ,
|
||||
//_command | SSD1963_CMD_ENTER_NORMAL_MODE ,
|
||||
//_command | SSD1963_CMD_EXIT_INVERT_MODE ,
|
||||
_command , SSD1963_CMD_EXIT_IDLE_MODE ,
|
||||
/*
|
||||
SSD1963_CMD_SET_TEAR_OFF ,
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
#define _ssd1963_wcmd(command) \
|
||||
do { \
|
||||
_ssd1963_clear_rs; \
|
||||
_ssd1963_write( command ); \
|
||||
_ssd1963_clear_wr; \
|
||||
_ssd1963_set_wr; \
|
||||
} while ( FALSE )
|
||||
#define _ssd1963_wdata(data) \
|
||||
do { \
|
||||
_ssd1963_set_rs; \
|
||||
_ssd1963_write( data ); \
|
||||
_ssd1963_clear_wr; \
|
||||
_ssd1963_set_wr; \
|
||||
} while ( FALSE )
|
||||
|
||||
|
||||
void _ssd1963_run_sequence( const u8 * sequence , u32 size )
|
||||
{
|
||||
_ssd1963_clear_cs;
|
||||
|
||||
u32 addr = 0;
|
||||
u8 has_command = 0 , has_data = 0 , has_delay = 0;
|
||||
while ( addr < size ) {
|
||||
if ( has_command ) {
|
||||
u16 command = sequence[ addr ++ ];
|
||||
_ssd1963_wcmd( command );
|
||||
has_command = 0;
|
||||
} else if ( has_data ) {
|
||||
u16 data = sequence[ addr ++ ];
|
||||
_ssd1963_wdata( data );
|
||||
has_data --;
|
||||
} else if ( has_delay ) {
|
||||
u8 delay = sequence[ addr ++ ];
|
||||
chThdSleep( delay );
|
||||
has_delay = 0;
|
||||
} else {
|
||||
u8 value = sequence[ addr ++ ];
|
||||
has_command = ( ( value & _command ) == _command );
|
||||
has_delay = ( ( value & _delay ) == _delay );
|
||||
has_data = value & ~( _command | _delay );
|
||||
}
|
||||
}
|
||||
|
||||
_ssd1963_set_cs;
|
||||
}
|
||||
|
||||
|
||||
void _ssd1963_reset_chip( void )
|
||||
static void _ssd1963_reset_chip( void )
|
||||
{
|
||||
// Select and reset the chip
|
||||
_ssd1963_set_reset;
|
||||
|
@ -178,29 +104,12 @@ void _ssd1963_reset_chip( void )
|
|||
chThdSleep( 100 );
|
||||
|
||||
// Run the PLL init sequence
|
||||
_ssd1963_run_sequence( _ssd1963_reset_sequence ,
|
||||
ssd1963RunSequence( _ssd1963_reset_sequence ,
|
||||
sizeof( _ssd1963_reset_sequence ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _ssd1963_set_pos( u32 x , u32 y )
|
||||
{
|
||||
_ssd1963_wcmd( 0x2a );
|
||||
_ssd1963_wdata( x >> 8 );
|
||||
_ssd1963_wdata( x & 0xff );
|
||||
_ssd1963_wdata( ( ( SSD1963_SCR_WIDTH - 1 ) >> 8 ) & 0xff );
|
||||
_ssd1963_wdata( ( SSD1963_SCR_WIDTH - 1 ) & 0xff );
|
||||
_ssd1963_wcmd( 0x2b );
|
||||
_ssd1963_wdata( y >> 8 );
|
||||
_ssd1963_wdata( y & 0xff );
|
||||
_ssd1963_wdata( ( ( SSD1963_SCR_HEIGHT - 1 ) >> 8 ) & 0xff );
|
||||
_ssd1963_wdata( ( SSD1963_SCR_HEIGHT - 1 ) & 0xff );
|
||||
_ssd1963_wcmd( 0x2c );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ssd1963Init( void )
|
||||
{
|
||||
_ssd1963_init_gpio( PAL_STM32_OSPEED_LOWEST );
|
||||
|
@ -209,58 +118,63 @@ void ssd1963Init( void )
|
|||
|
||||
chThdSleep( 10 );
|
||||
_ssd1963_init_gpio( PAL_STM32_OSPEED_HIGHEST );
|
||||
_ssd1963_run_sequence( _ssd1963_init_sequence ,
|
||||
ssd1963RunSequence( _ssd1963_init_sequence ,
|
||||
sizeof( _ssd1963_init_sequence ) );
|
||||
|
||||
_ssd1963_clear_cs;
|
||||
_ssd1963_set_pos( 0 , 0 );
|
||||
ssd1963StartWriting( 0 , 0 );
|
||||
int i;
|
||||
for ( i = 0 ; i < SSD1963_SCR_HEIGHT ; i ++ ) {
|
||||
u16 j , c = 0x8000;
|
||||
for ( j = 0 ; j < SSD1963_SCR_WIDTH ; j ++ ) {
|
||||
if ( ( j & 7 ) == 7 ) {
|
||||
c >>= 1;
|
||||
if ( !c ) {
|
||||
c = 0x8000;
|
||||
}
|
||||
}
|
||||
_ssd1963_wdata( c );
|
||||
}
|
||||
for ( i = 0 ; i < SSD1963_SCR_HEIGHT * SSD1963_SCR_WIDTH ; i ++ ) {
|
||||
ssd1963WriteData( 0 );
|
||||
}
|
||||
_ssd1963_set_cs;
|
||||
}
|
||||
|
||||
|
||||
void display_test_pattern( u16 start_mask )
|
||||
void ssd1963RunSequence( const u8 * sequence , u32 size )
|
||||
{
|
||||
_ssd1963_clear_cs;
|
||||
_ssd1963_set_pos( 0 , 0 );
|
||||
int i;
|
||||
for ( i = 0 ; i < SSD1963_SCR_HEIGHT ; i ++ ) {
|
||||
u16 j , c = start_mask;
|
||||
for ( j = 0 ; j < SSD1963_SCR_WIDTH ; j ++ ) {
|
||||
if ( ( j & 7 ) == 7 ) {
|
||||
c >>= 1;
|
||||
if ( !c ) {
|
||||
c = 0x8000;
|
||||
}
|
||||
}
|
||||
_ssd1963_wdata( c );
|
||||
|
||||
u32 addr = 0;
|
||||
u8 has_command = 0 , has_data = 0 , has_delay = 0;
|
||||
while ( addr < size ) {
|
||||
if ( has_command ) {
|
||||
u16 command = sequence[ addr ++ ];
|
||||
ssd1963WriteCommand( command );
|
||||
has_command = 0;
|
||||
} else if ( has_data ) {
|
||||
u16 data = sequence[ addr ++ ];
|
||||
ssd1963WriteData( data );
|
||||
has_data --;
|
||||
} else if ( has_delay ) {
|
||||
u8 delay = sequence[ addr ++ ];
|
||||
chThdSleep( delay );
|
||||
has_delay = 0;
|
||||
} else {
|
||||
u8 value = sequence[ addr ++ ];
|
||||
has_command = ( ( value & SSD1963_COMMAND )
|
||||
== SSD1963_COMMAND );
|
||||
has_delay = ( ( value & SSD1963_DELAY )
|
||||
== SSD1963_DELAY );
|
||||
has_data = value & ~( SSD1963_COMMAND | SSD1963_DELAY );
|
||||
}
|
||||
}
|
||||
|
||||
_ssd1963_set_cs;
|
||||
}
|
||||
|
||||
|
||||
void display_off( void )
|
||||
void ssd1963StartWriting( u32 x , u32 y )
|
||||
{
|
||||
static int display = 1;
|
||||
display = !display;
|
||||
_ssd1963_clear_cs;
|
||||
if ( display ) {
|
||||
_ssd1963_wcmd( SSD1963_CMD_SET_DISPLAY_ON );
|
||||
} else {
|
||||
_ssd1963_wcmd( SSD1963_CMD_SET_DISPLAY_OFF );
|
||||
}
|
||||
_ssd1963_set_cs;
|
||||
ssd1963WriteCommand( 0x2a );
|
||||
ssd1963WriteData( x >> 8 );
|
||||
ssd1963WriteData( x & 0xff );
|
||||
ssd1963WriteData( ( ( SSD1963_SCR_WIDTH - 1 ) >> 8 ) & 0xff );
|
||||
ssd1963WriteData( ( SSD1963_SCR_WIDTH - 1 ) & 0xff );
|
||||
ssd1963WriteCommand( 0x2b );
|
||||
ssd1963WriteData( y >> 8 );
|
||||
ssd1963WriteData( y & 0xff );
|
||||
ssd1963WriteData( ( ( SSD1963_SCR_HEIGHT - 1 ) >> 8 ) & 0xff );
|
||||
ssd1963WriteData( ( SSD1963_SCR_HEIGHT - 1 ) & 0xff );
|
||||
ssd1963WriteCommand( 0x2c );
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#define SSD1963_CMD_SET_DISPLAY_OFF 0x28
|
||||
#define SSD1963_CMD_SET_DISPLAY_ON 0x29
|
||||
#define SSD1963_CMD_SET_TEAR_OFF 0x34
|
||||
#define SSD1963_CMD_SET_ADDRESS_MODE 0x36
|
||||
#define SSD1963_CMD_EXIT_IDLE_MODE 0x38
|
||||
#define SSD1963_CMD_SET_LCD_MODE 0xb0
|
||||
#define SSD1963_CMD_SET_HORI_PERIOD 0xb4
|
||||
|
@ -34,15 +35,40 @@
|
|||
#define SSD1963_CMD_SET_PIXEL_FORMAT 0xf0
|
||||
|
||||
|
||||
|
||||
// Control and data ports
|
||||
#define ssd1963Ctrl (*((__IO u16 *) 0x60000000))
|
||||
#define ssd1963Data (*((__IO u16 *) 0x60020000))
|
||||
|
||||
// Command sequences
|
||||
#define SSD1963_DATA(x) ( (u8)( (x) & 0x3f) )
|
||||
#define SSD1963_COMMAND 0x40
|
||||
#define SSD1963_DELAY 0x80
|
||||
|
||||
|
||||
// Initialise the display controller
|
||||
void ssd1963Init( void );
|
||||
|
||||
// Execute a sequence of commands from the specified address
|
||||
void ssd1963RunSequence( const u8 * sequence , u32 size );
|
||||
|
||||
|
||||
// Write a command to the SSD1963
|
||||
#define ssd1963WriteCommand(command) \
|
||||
do { \
|
||||
_ssd1963_clear_rs; \
|
||||
_ssd1963_write( command ); \
|
||||
_ssd1963_clear_wr; \
|
||||
_ssd1963_set_wr; \
|
||||
} while ( FALSE )
|
||||
|
||||
// Write data to the SSD1963
|
||||
#define ssd1963WriteData(data) \
|
||||
do { \
|
||||
_ssd1963_set_rs; \
|
||||
_ssd1963_write( data ); \
|
||||
_ssd1963_clear_wr; \
|
||||
_ssd1963_set_wr; \
|
||||
} while ( FALSE )
|
||||
|
||||
|
||||
// Start writing data at the specified location
|
||||
void ssd1963StartWriting( u32 x , u32 y );
|
||||
|
||||
|
||||
#endif // _H_SSD1963_STM32F4
|
||||
|
|
125
07-BitBangDisplay/xpt2046.c
Normal file
125
07-BitBangDisplay/xpt2046.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
#include "xpt2046.h"
|
||||
|
||||
static const SPIConfig _xpt2046_spi_config = {
|
||||
NULL ,
|
||||
XPT2046_NSS_PORT ,
|
||||
XPT2046_NSS_PAD ,
|
||||
SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0
|
||||
};
|
||||
|
||||
|
||||
|
||||
u16 _xpt2046_get_reading( u8 control )
|
||||
{
|
||||
u8 tData[3] = { control , 0 , 0 };
|
||||
u8 rData[3] = { 0 , 0 , 0 };
|
||||
|
||||
#if SPI_USE_MUTUAL_EXCLUSION
|
||||
spiAcquireBus( &( XPT2046_SPI_DRIVER ) );
|
||||
#endif
|
||||
|
||||
palClearPad( XPT2046_NSS_PORT , XPT2046_NSS_PAD );
|
||||
spiExchange( &( XPT2046_SPI_DRIVER ) , 3 , tData , rData );
|
||||
palSetPad( XPT2046_NSS_PORT , XPT2046_NSS_PAD );
|
||||
|
||||
#if SPI_USE_MUTUAL_EXCLUSION
|
||||
spiReleaseBus( &( XPT2046_SPI_DRIVER ) );
|
||||
#endif
|
||||
|
||||
if ( ( control & 0x08 ) == 0 ) {
|
||||
return ( rData[1] << 5 ) | ( rData[2] >> 3 );
|
||||
}
|
||||
return ( rData[1] << 4 ) | ( rData[2] >> 4 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void xpt2046Init( void )
|
||||
{
|
||||
// Initialise SPI
|
||||
spiStart( &( XPT2046_SPI_DRIVER ) , &_xpt2046_spi_config );
|
||||
|
||||
// NSS signal
|
||||
palSetPadMode( XPT2046_NSS_PORT , XPT2046_NSS_PAD ,
|
||||
PAL_MODE_OUTPUT_PUSHPULL );
|
||||
palSetPad( XPT2046_NSS_PORT , XPT2046_NSS_PAD );
|
||||
|
||||
// Main SPI signals
|
||||
palSetPadMode( XPT2046_CLK_PORT , XPT2046_CLK_PAD ,
|
||||
PAL_MODE_ALTERNATE( 5 ) );
|
||||
palSetPadMode( XPT2046_DIN_PORT , XPT2046_DIN_PAD ,
|
||||
PAL_MODE_ALTERNATE( 5 ) );
|
||||
palSetPadMode( XPT2046_DOUT_PORT , XPT2046_DOUT_PAD ,
|
||||
PAL_MODE_ALTERNATE( 5 ) );
|
||||
|
||||
// PENIRQ signal
|
||||
palSetPadMode( XPT2046_IRQ_PORT , XPT2046_IRQ_PAD , PAL_MODE_INPUT );
|
||||
|
||||
// Read a sample, leaving PENIRQ active
|
||||
_xpt2046_get_reading( 0x90 );
|
||||
}
|
||||
|
||||
|
||||
int xpt2046GetCoordinates( int * pX , int * pY )
|
||||
{
|
||||
int i;
|
||||
int allX[ 7 ] , allY[ 7 ];
|
||||
_xpt2046_get_reading( 0xd1 );
|
||||
_xpt2046_get_reading( 0x91 );
|
||||
for ( i = 0 ; i < 7 ; i ++ ) {
|
||||
allX[ i ] = _xpt2046_get_reading( 0xd1 );
|
||||
allY[ i ] = _xpt2046_get_reading( 0x91 );
|
||||
}
|
||||
|
||||
int j;
|
||||
for ( i = 0 ; i < 4 ; i ++ ) {
|
||||
for ( j = i ; j < 7 ; j ++ ) {
|
||||
int temp = allX[ i ];
|
||||
if ( temp > allX[ j ] ) {
|
||||
allX[ i ] = allX[ j ];
|
||||
allX[ j ] = temp;
|
||||
}
|
||||
temp = allY[ i ];
|
||||
if ( temp > allY[ j ] ) {
|
||||
allY[ i ] = allY[ j ];
|
||||
allY[ j ] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
_xpt2046_get_reading( 0x90 );
|
||||
|
||||
if ( palReadPad( XPT2046_IRQ_PORT , XPT2046_IRQ_PAD ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pX = allX[ 3 ];
|
||||
*pY = allY[ 3 ];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xpt2046GetAverageCoordinates( int * pX , int * pY , int nSamples )
|
||||
{
|
||||
int nRead = 0;
|
||||
int xAcc = 0 , yAcc = 0;
|
||||
int x , y;
|
||||
|
||||
while ( nRead < nSamples ) {
|
||||
if ( !xpt2046GetCoordinates( &x , &y ) ) {
|
||||
break;
|
||||
}
|
||||
xAcc += x;
|
||||
yAcc += y;
|
||||
nRead ++;
|
||||
}
|
||||
|
||||
if ( nRead == 0 ) {
|
||||
return 0;
|
||||
}
|
||||
*pX = xAcc / nRead;
|
||||
*pY = yAcc / nRead;
|
||||
return 1;
|
||||
}
|
31
07-BitBangDisplay/xpt2046.h
Normal file
31
07-BitBangDisplay/xpt2046.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef _H_XPT2046_STM32F4
|
||||
#define _H_XPT2046_STM32F4
|
||||
|
||||
|
||||
// Ports and controllers for the various touchscreen pins
|
||||
// IRQ (any port will do)
|
||||
#define XPT2046_IRQ_PORT GPIOC
|
||||
#define XPT2046_IRQ_PAD 4
|
||||
// NSS (any port will do, this is done manually)
|
||||
#define XPT2046_NSS_PORT GPIOA
|
||||
#define XPT2046_NSS_PAD 4
|
||||
// CLK (must be a SPI clock port)
|
||||
#define XPT2046_CLK_PORT GPIOA
|
||||
#define XPT2046_CLK_PAD 5
|
||||
// DIN (must be a SPI MOSI port)
|
||||
#define XPT2046_DIN_PORT GPIOA
|
||||
#define XPT2046_DIN_PAD 7
|
||||
// DOUT (must be a SPI MISO port)
|
||||
#define XPT2046_DOUT_PORT GPIOA
|
||||
#define XPT2046_DOUT_PAD 6
|
||||
|
||||
// SPI driver to use
|
||||
#define XPT2046_SPI_DRIVER SPID1
|
||||
|
||||
|
||||
void xpt2046Init( void );
|
||||
int xpt2046GetCoordinates( int * pX , int * pY );
|
||||
int xpt2046GetAverageCoordinates( int * pX , int * pY , int nSamples );
|
||||
|
||||
|
||||
#endif //_H_XPT2046_STM32F4
|
Loading…
Reference in a new issue