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
|
PROJECT = BitBangDisplay
|
||||||
PRJ_C_SRC = main.c \
|
PRJ_C_SRC = main.c \
|
||||||
ssd1963.c
|
ssd1963.c \
|
||||||
|
xpt2046.c
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# Build global options
|
# Build global options
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "hal.h"
|
#include "hal.h"
|
||||||
|
|
||||||
#include "ssd1963.h"
|
#include "ssd1963.h"
|
||||||
|
#include "xpt2046.h"
|
||||||
|
|
||||||
// This is called when the board boots up with the user button pressed. The
|
// 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
|
// 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 );
|
static void displayTestPattern( u16 start_mask )
|
||||||
void display_test_pattern( 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 )
|
int main( void )
|
||||||
{
|
{
|
||||||
|
@ -27,14 +108,18 @@ int main( void )
|
||||||
lockdown( );
|
lockdown( );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xpt2046Init( );
|
||||||
|
initIRQs();
|
||||||
ssd1963Init( );
|
ssd1963Init( );
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
display_test_pattern( 1 << i );
|
displayTestPattern( 1 << i );
|
||||||
|
chThdSleep(100);
|
||||||
i = ( i + 1 ) % 16;
|
i = ( i + 1 ) % 16;
|
||||||
if ( palReadPad( GPIOA , GPIOA_BUTTON ) ) {
|
if ( tryReading ) {
|
||||||
display_off( );
|
checkTouchScreen( );
|
||||||
|
tryReading = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,66 +4,43 @@
|
||||||
#include "ssd1963.h"
|
#include "ssd1963.h"
|
||||||
|
|
||||||
|
|
||||||
#define _command 0x40
|
|
||||||
#define _delay 0x80
|
|
||||||
#define _ndata(x) ( (u8)( (x) & 0x3f) )
|
|
||||||
|
|
||||||
static const u8 _ssd1963_reset_sequence[ ] = {
|
static const u8 _ssd1963_reset_sequence[ ] = {
|
||||||
/*
|
// PLL configuration
|
||||||
* PLL configuration
|
SSD1963_COMMAND | SSD1963_DATA(3) ,
|
||||||
* -----------------
|
|
||||||
*
|
|
||||||
* 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) ,
|
|
||||||
SSD1963_CMD_SET_PLL_MN ,
|
SSD1963_CMD_SET_PLL_MN ,
|
||||||
0x31 , 0x05 , 0x04 ,
|
0x1e , 0x02 , 0x04 ,
|
||||||
// 0x1e , 0x02 , 0x04 ,
|
|
||||||
|
|
||||||
// Enable PLL and wait until it's stable
|
// Enable PLL and wait until it's stable
|
||||||
_command | _delay | _ndata(1) ,
|
SSD1963_COMMAND | SSD1963_DELAY | SSD1963_DATA(1) ,
|
||||||
SSD1963_CMD_SET_PLL , 1 ,
|
SSD1963_CMD_SET_PLL , 1 ,
|
||||||
1 ,
|
1 ,
|
||||||
|
|
||||||
// Fully enable PLL
|
// Fully enable PLL
|
||||||
_command | _ndata(1) ,
|
SSD1963_COMMAND | SSD1963_DATA(1) ,
|
||||||
SSD1963_CMD_SET_PLL , 3 ,
|
SSD1963_CMD_SET_PLL , 3 ,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static const u8 _ssd1963_init_sequence[ ] = {
|
static const u8 _ssd1963_init_sequence[ ] = {
|
||||||
// Software reset
|
// Software reset
|
||||||
_command | _delay ,
|
SSD1963_COMMAND | SSD1963_DELAY ,
|
||||||
SSD1963_CMD_SOFT_RESET ,
|
SSD1963_CMD_SOFT_RESET ,
|
||||||
5 ,
|
5 ,
|
||||||
|
|
||||||
/* Pixel clock: screw finesse, crank that up to the max */
|
// Pixel clock: screw finesse, crank that up to the max
|
||||||
_command | _ndata( 3 ) | _delay ,
|
SSD1963_COMMAND | SSD1963_DATA( 3 ) | SSD1963_DELAY ,
|
||||||
SSD1963_CMD_SET_LSHIFT_FREQ ,
|
SSD1963_CMD_SET_LSHIFT_FREQ ,
|
||||||
0x07 , 0xff , 0xff ,
|
0x07 , 0xff , 0xff ,
|
||||||
15 ,
|
15 ,
|
||||||
|
|
||||||
// Use 565 RGB format
|
// Use 565 RGB format
|
||||||
_command | _delay | _ndata(1) ,
|
SSD1963_COMMAND | SSD1963_DELAY | SSD1963_DATA(1) ,
|
||||||
SSD1963_CMD_SET_PIXEL_FORMAT ,
|
SSD1963_CMD_SET_PIXEL_FORMAT ,
|
||||||
0x03 ,
|
0x03 ,
|
||||||
5 ,
|
5 ,
|
||||||
|
|
||||||
// Setup LCD panel
|
// Setup LCD panel
|
||||||
_command | _ndata( 7 ) ,
|
SSD1963_COMMAND | SSD1963_DATA( 7 ) ,
|
||||||
SSD1963_CMD_SET_LCD_MODE ,
|
SSD1963_CMD_SET_LCD_MODE ,
|
||||||
0x20 , // Data width 24-bit, FRC and dithering disabled
|
0x20 , // Data width 24-bit, FRC and dithering disabled
|
||||||
// Data latch on falling edge
|
// Data latch on falling edge
|
||||||
|
@ -78,7 +55,7 @@ static const u8 _ssd1963_init_sequence[ ] = {
|
||||||
( ( SSD1963_SCR_HEIGHT - 1 ) & 0xff ) ,
|
( ( SSD1963_SCR_HEIGHT - 1 ) & 0xff ) ,
|
||||||
0x00 , // Ignored (serial interface)
|
0x00 , // Ignored (serial interface)
|
||||||
|
|
||||||
_command | _ndata( 8 ) ,
|
SSD1963_COMMAND | SSD1963_DATA( 8 ) ,
|
||||||
SSD1963_CMD_SET_HORI_PERIOD ,
|
SSD1963_CMD_SET_HORI_PERIOD ,
|
||||||
0x02 , 0x13 , // Total period (PCLK)
|
0x02 , 0x13 , // Total period (PCLK)
|
||||||
0x00 , 0x08 , // Non-display period
|
0x00 , 0x08 , // Non-display period
|
||||||
|
@ -86,86 +63,35 @@ static const u8 _ssd1963_init_sequence[ ] = {
|
||||||
0x00 , 0x02 , // Start location (PCLK)
|
0x00 , 0x02 , // Start location (PCLK)
|
||||||
0x00 , // Ignored (serial interfaces)
|
0x00 , // Ignored (serial interfaces)
|
||||||
|
|
||||||
_command | _ndata( 7 ) ,
|
SSD1963_COMMAND | SSD1963_DATA( 7 ) ,
|
||||||
SSD1963_CMD_SET_VERT_PERIOD ,
|
SSD1963_CMD_SET_VERT_PERIOD ,
|
||||||
0x01 , 0x20 , // Vertical total period
|
0x01 , 0x20 , // Vertical total period
|
||||||
0x00 , 0x04 , // Non-display period
|
0x00 , 0x04 , // Non-display period
|
||||||
0x0c , // Sync pulse width
|
0x0c , // Sync pulse width
|
||||||
0x00 , 0x02 , // Start location
|
0x00 , 0x02 , // Start location
|
||||||
|
|
||||||
_command | _ndata(1) ,
|
SSD1963_COMMAND | SSD1963_DATA(1) ,
|
||||||
0x36 ,
|
SSD1963_CMD_SET_ADDRESS_MODE ,
|
||||||
0x00 ,
|
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_CMD_SET_DISPLAY_ON ,
|
SSD1963_COMMAND ,
|
||||||
|
|
||||||
_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 ,
|
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 ,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define _ssd1963_wcmd(command) \
|
static void _ssd1963_reset_chip( void )
|
||||||
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 )
|
|
||||||
{
|
{
|
||||||
// Select and reset the chip
|
// Select and reset the chip
|
||||||
_ssd1963_set_reset;
|
_ssd1963_set_reset;
|
||||||
|
@ -178,29 +104,12 @@ void _ssd1963_reset_chip( void )
|
||||||
chThdSleep( 100 );
|
chThdSleep( 100 );
|
||||||
|
|
||||||
// Run the PLL init sequence
|
// Run the PLL init sequence
|
||||||
_ssd1963_run_sequence( _ssd1963_reset_sequence ,
|
ssd1963RunSequence( _ssd1963_reset_sequence ,
|
||||||
sizeof( _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 )
|
void ssd1963Init( void )
|
||||||
{
|
{
|
||||||
_ssd1963_init_gpio( PAL_STM32_OSPEED_LOWEST );
|
_ssd1963_init_gpio( PAL_STM32_OSPEED_LOWEST );
|
||||||
|
@ -209,58 +118,63 @@ void ssd1963Init( void )
|
||||||
|
|
||||||
chThdSleep( 10 );
|
chThdSleep( 10 );
|
||||||
_ssd1963_init_gpio( PAL_STM32_OSPEED_HIGHEST );
|
_ssd1963_init_gpio( PAL_STM32_OSPEED_HIGHEST );
|
||||||
_ssd1963_run_sequence( _ssd1963_init_sequence ,
|
ssd1963RunSequence( _ssd1963_init_sequence ,
|
||||||
sizeof( _ssd1963_init_sequence ) );
|
sizeof( _ssd1963_init_sequence ) );
|
||||||
|
|
||||||
_ssd1963_clear_cs;
|
_ssd1963_clear_cs;
|
||||||
_ssd1963_set_pos( 0 , 0 );
|
ssd1963StartWriting( 0 , 0 );
|
||||||
int i;
|
int i;
|
||||||
for ( i = 0 ; i < SSD1963_SCR_HEIGHT ; i ++ ) {
|
for ( i = 0 ; i < SSD1963_SCR_HEIGHT * SSD1963_SCR_WIDTH ; i ++ ) {
|
||||||
u16 j , c = 0x8000;
|
ssd1963WriteData( 0 );
|
||||||
for ( j = 0 ; j < SSD1963_SCR_WIDTH ; j ++ ) {
|
|
||||||
if ( ( j & 7 ) == 7 ) {
|
|
||||||
c >>= 1;
|
|
||||||
if ( !c ) {
|
|
||||||
c = 0x8000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ssd1963_wdata( c );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ssd1963_set_cs;
|
_ssd1963_set_cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void display_test_pattern( u16 start_mask )
|
void ssd1963RunSequence( const u8 * sequence , u32 size )
|
||||||
{
|
{
|
||||||
_ssd1963_clear_cs;
|
_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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ssd1963_set_cs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
u32 addr = 0;
|
||||||
void display_off( void )
|
u8 has_command = 0 , has_data = 0 , has_delay = 0;
|
||||||
{
|
while ( addr < size ) {
|
||||||
static int display = 1;
|
if ( has_command ) {
|
||||||
display = !display;
|
u16 command = sequence[ addr ++ ];
|
||||||
_ssd1963_clear_cs;
|
ssd1963WriteCommand( command );
|
||||||
if ( display ) {
|
has_command = 0;
|
||||||
_ssd1963_wcmd( SSD1963_CMD_SET_DISPLAY_ON );
|
} 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 {
|
} else {
|
||||||
_ssd1963_wcmd( SSD1963_CMD_SET_DISPLAY_OFF );
|
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;
|
_ssd1963_set_cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ssd1963StartWriting( u32 x , u32 y )
|
||||||
|
{
|
||||||
|
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_OFF 0x28
|
||||||
#define SSD1963_CMD_SET_DISPLAY_ON 0x29
|
#define SSD1963_CMD_SET_DISPLAY_ON 0x29
|
||||||
#define SSD1963_CMD_SET_TEAR_OFF 0x34
|
#define SSD1963_CMD_SET_TEAR_OFF 0x34
|
||||||
|
#define SSD1963_CMD_SET_ADDRESS_MODE 0x36
|
||||||
#define SSD1963_CMD_EXIT_IDLE_MODE 0x38
|
#define SSD1963_CMD_EXIT_IDLE_MODE 0x38
|
||||||
#define SSD1963_CMD_SET_LCD_MODE 0xb0
|
#define SSD1963_CMD_SET_LCD_MODE 0xb0
|
||||||
#define SSD1963_CMD_SET_HORI_PERIOD 0xb4
|
#define SSD1963_CMD_SET_HORI_PERIOD 0xb4
|
||||||
|
@ -34,15 +35,40 @@
|
||||||
#define SSD1963_CMD_SET_PIXEL_FORMAT 0xf0
|
#define SSD1963_CMD_SET_PIXEL_FORMAT 0xf0
|
||||||
|
|
||||||
|
|
||||||
|
// Command sequences
|
||||||
// Control and data ports
|
#define SSD1963_DATA(x) ( (u8)( (x) & 0x3f) )
|
||||||
#define ssd1963Ctrl (*((__IO u16 *) 0x60000000))
|
#define SSD1963_COMMAND 0x40
|
||||||
#define ssd1963Data (*((__IO u16 *) 0x60020000))
|
#define SSD1963_DELAY 0x80
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Initialise the display controller
|
// Initialise the display controller
|
||||||
void ssd1963Init( void );
|
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
|
#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