changeset 8:58d76cf522ff

Split out code into separate files.
author Daniel O'Connor <darius@dons.net.au>
date Sat, 04 Feb 2012 13:29:31 +1030
parents 9404b9869c27
children be0a1ac64d97
files BSDmakefile delay.c delay.h flash.c flash.h hw.c hw.h lcd.c lcd.h main.c spi.c spi.h touch.c touch.h
diffstat 14 files changed, 699 insertions(+), 553 deletions(-) [+]
line wrap: on
line diff
--- a/BSDmakefile	Sun Jan 22 17:10:51 2012 +1030
+++ b/BSDmakefile	Sat Feb 04 13:29:31 2012 +1030
@@ -2,12 +2,17 @@
 
 SRCS=		comm.c \
 		core_cm3.c \
+		delay.c \
+		flash.c \
+		hw.c \
 		lcd.c \
 		main.c \
 		misc.c \
+		spi.c \
 		startup_stm32f10x_md_mthomas.c \
 		syscalls.c \
-		system_stm32f10x.c
+		system_stm32f10x.c \
+		touch.c
 
 STM32LIBS=	usart gpio rcc rtc pwr bkp fsmc spi tim
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/delay.c	Sat Feb 04 13:29:31 2012 +1030
@@ -0,0 +1,14 @@
+#include <stdint.h>
+#include "stm32f10x.h"
+#include "delay.h"
+
+/* This is a bit rough and ready */
+void
+delay(__IO uint32_t nCount) {
+    __IO uint32_t i;
+    
+    for(; nCount != 0; nCount--)
+	for (i = 0; i < 3900; i++)
+	    ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/delay.h	Sat Feb 04 13:29:31 2012 +1030
@@ -0,0 +1,3 @@
+void	delay(__IO uint32_t nCount);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash.c	Sat Feb 04 13:29:31 2012 +1030
@@ -0,0 +1,57 @@
+#include <stdint.h>
+
+#include "stm32f10x.h"
+#include "spi.h"
+#include "flash.h"
+
+#define FL_SELECT()	GPIO_ResetBits(GPIOA, GPIO_Pin_4)
+#define FL_DESELECT()	GPIO_SetBits(GPIOA, GPIO_Pin_4)
+
+uint16_t
+flashreadid(void) {
+    uint8_t	fac, dev;
+    
+    FL_SELECT();			/* Select device */
+
+    SPI_WriteByte(FL_RDID);		/* Send command */
+    SPI_WriteByte(0x00);		/* Send address cycles (ID data starts at 0) */
+    SPI_WriteByte(0x00);
+    SPI_WriteByte(0x00);
+    fac = SPI_WriteByte(0x00);		/* Read ID */
+    dev = SPI_WriteByte(0x00);
+  
+    FL_DESELECT();			/* De-select device */
+
+    return fac << 8 | dev;
+}
+
+uint8_t
+flashreadstatus(void) {
+    uint8_t	status;
+    
+    FL_SELECT();			/* Select device */
+
+    SPI_WriteByte(FL_RDSR);		/* Send command */
+    SPI_WriteByte(0x00);		/* Send dummy byte for address cycle */
+    status = SPI_WriteByte(0x00);	/* Read status */
+  
+    FL_DESELECT();			/* De-select device */
+
+    return status;
+}
+
+void
+flashwritestatus(uint8_t status) {
+    /* Enable status write */
+    FL_SELECT();			/* Select device */
+    SPI_WriteByte(FL_EWSR);		/* Send command */
+    SPI_WriteByte(0x00);		/* Send data byte */
+    FL_DESELECT();
+
+    /* Actually write status */
+    FL_SELECT();			/* Re-select device for new command */			
+    SPI_WriteByte(FL_WRSR);		/* Send command */
+    SPI_WriteByte(status);		/* Send data byte */
+    FL_DESELECT();			/* De-select device */
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flash.h	Sat Feb 04 13:29:31 2012 +1030
@@ -0,0 +1,29 @@
+uint16_t	flashreadid(void);
+uint8_t		flashreadstatus(void);
+void		flashwritestatus(uint8_t status);
+void		flashwritectl(int enable);
+
+#define FL_BP0		(1<<2)
+#define FL_BP1		(1<<3)
+#define FL_BP2		(1<<4)
+#define FL_BP3		(1<<5)
+#define FL_BPL		(1<<7)
+
+#define FL_READ		0x03
+#define FL_HSREAD	0x0b
+#define FL_32KERASE	0x52
+#define FL_64KERASE	0xd8
+#define FL_CHIPERASE	0x60
+#define FL_BYTEPROG	0x02
+#define FL_AAIWP	0xad
+#define FL_RDSR		0x05
+#define FL_EWSR		0x50
+#define FL_WRSR		0x01
+#define FL_WREN		0x06
+#define FL_WRDI		0x04
+#define FL_RDID		0x90
+#define FL_JEDECID	0x9f
+#define FL_EBSY		0x70
+#define FL_DBSY		0x80
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hw.c	Sat Feb 04 13:29:31 2012 +1030
@@ -0,0 +1,263 @@
+#include <stdint.h>
+#include "stm32f10x.h"
+#include "lcd.h"
+
+static void	hw_port_cfg(void);
+
+
+void hw_init(void) {
+    hw_port_cfg();
+    lcd_init();
+    lcd_setpwm(1000);
+}
+
+static void
+hw_port_cfg(void) {
+    GPIO_InitTypeDef			GPIO_InitStructure;
+    USART_InitTypeDef USART_InitStructure;
+    SPI_InitTypeDef			SPI_InitStructure;
+    FSMC_NORSRAMInitTypeDef		FSMC_NORSRAMInitStructure;
+    FSMC_NORSRAMTimingInitTypeDef	p;
+    TIM_TimeBaseInitTypeDef		TIM_TimeBaseStructure;
+    
+    /* RTC stuff */
+    /* Enable PWR and BKP clocks */
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
+
+    /* Allow access to BKP Domain */
+    PWR_BackupAccessCmd(ENABLE);
+
+    /* Reset Backup Domain
+     *
+     * This resets the RTC etc back to 0 so probably only useful under user command
+     BKP_DeInit();
+    */
+
+    /* Enable Low Speed External clock */
+    RCC_LSEConfig(RCC_LSE_ON);
+
+    /* Wait till LSE is ready */
+    while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
+	;
+
+    /* Select LSE as RTC Clock Source */
+    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
+
+    /* Enable RTC Clock */
+    RCC_RTCCLKCmd(ENABLE);
+
+    /* Wait for RTC registers synchronization */
+    RTC_WaitForSynchro();
+
+    /* Wait until last write operation on RTC registers has finished */
+    RTC_WaitForLastTask();
+
+    /* Wait until last write operation on RTC registers has finished */
+    RTC_WaitForLastTask();
+
+    /* Set RTC prescaler: set RTC period to 1sec */
+    RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */
+
+    /* Wait until last write operation on RTC registers has finished */
+    RTC_WaitForLastTask();
+
+    /* Clock setup */
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
+
+    /* Port configuration */
+    /* Configure USART1 TX (PA.09) as alternate function push-pull */
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
+    GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+    /* Configure USART1 RX (PA.10) as input floating */
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
+    GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+    /* Enable GPIOB clock */
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
+
+    /* Configure PB5 as output push-pull for LED */
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
+    GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+    /* Configure PB15 as input pull-up push-pull for push button */
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
+    GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+    /* USART configuration */
+    /* USART1 - 115200 8n1, no flow control TX & RX enabled */
+    USART_InitStructure.USART_BaudRate = 115200;
+    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
+    USART_InitStructure.USART_StopBits = USART_StopBits_1;
+    USART_InitStructure.USART_Parity = USART_Parity_No;
+    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+    USART_Init(USART1, &USART_InitStructure);
+
+    /* Enable interrupts on receive data */
+    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
+
+    /* Enable USART */
+    USART_Cmd(USART1, ENABLE);
+
+    /* Enable FSMC clock */
+    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
+
+    /* Enable alternate function IO clock */
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
+
+    /* Enable GPIOD clock */
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
+
+    /* Enable GPIOD clock */
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
+
+    /* Configures LCD Control lines (FSMC Pins) in alternate function Push-Pull mode.
+     *
+     * PD0(D2), PD1(D3), PD4(NOE), PD5(NWE), PD7(NE1/CS), PD8(D13), PD9(D14),
+     * PD10(D15), PD11(A16/RS) PD14(D0), PD15(D1)
+     */
+    GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 |
+				   GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | 
+				   GPIO_Pin_14 | GPIO_Pin_15);
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
+    GPIO_Init(GPIOD, &GPIO_InitStructure);
+
+    /* PE7(D4), PE8(D5), PE9(D6), PE10(D7), PE11(D8), PE12(D9), PE13(D10),
+     * PE14(D11), PE15(D12)
+     */
+    GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | 
+				   GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
+				   GPIO_Pin_15);
+    GPIO_Init(GPIOE, &GPIO_InitStructure);
+
+    /* Configure backlight control (PD13/FSMC_A18 remapped to TIM4_CH2) */
+    /* Enable TIM4 clock */
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
+
+    /* Enable timer function
+     * Note source clock is SYSCLK / 2 = 36MHz
+     */
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
+    GPIO_Init(GPIOD, &GPIO_InitStructure);
+
+    /* Remap TIM4_CH2 to PD13 */
+    GPIO_PinRemapConfig(GPIO_Remap_TIM4, ENABLE);
+    
+    /* Reset TIM4 */
+    TIM_DeInit(TIM4);
+
+    /* Time Base configuration */
+    TIM_TimeBaseStructure.TIM_Period = 999;
+    TIM_TimeBaseStructure.TIM_Prescaler = 0;
+    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
+    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down;
+
+    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
+
+    /* Enable timer */
+    TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
+    TIM_ARRPreloadConfig(TIM4, ENABLE);
+    TIM_Cmd(TIM4, ENABLE);
+
+    /* Configure reset pin (PE1) as GPIO out PP */
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
+    GPIO_Init(GPIOE, &GPIO_InitStructure);
+
+    /* Configures the Parallel interface (FSMC) for LCD (Parallel mode) */
+    /* Timing configuration */
+    p.FSMC_AddressSetupTime = 5;
+    p.FSMC_AddressHoldTime = 5;
+    p.FSMC_DataSetupTime = 5;
+    p.FSMC_BusTurnAroundDuration = 0;
+    p.FSMC_CLKDivision = 0;
+    p.FSMC_DataLatency = 0;
+    p.FSMC_AccessMode = FSMC_AccessMode_A;
+
+    /* FSMC_Bank1_NORSRAM1 configured as follows:
+       - Data/Address MUX = Disable
+       - Memory Type = SRAM
+       - Data Width = 16bit
+       - Write Operation = Enable
+       - Extended Mode = Disable
+       - Asynchronous Wait = Disable */
+    FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
+    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
+    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
+    FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
+    FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
+    FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
+    FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
+    FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
+    FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
+    FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);  
+
+    /* Enable FSMC_Bank1_NORSRAM1 */
+    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
+
+    /* Configure touch screen controller
+     *
+     * Connected to SPI1 which is shared with the AT45DB161D.
+     *
+     * The touch screen is selected with PB7.
+     * The flash chip is selected with PA4.
+     */
+
+    /* Enable SPI1 clock */
+    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
+
+    /* Configure MOSI, MISO and SCLK as alternate function PP */
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
+    GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+    /* Configure flash chip select pin (PA4) as GPIO out PP */
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
+    GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+    /* Configure touch chip select pin (PB7) as GPIO out PP */
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
+    GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+    /* De-select touch & flash */
+    GPIO_SetBits(GPIOA, GPIO_Pin_4);
+    GPIO_SetBits(GPIOB, GPIO_Pin_7);
+    
+    /* SPI1 Config */
+    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
+    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
+    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
+    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
+    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
+    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
+    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
+    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
+    SPI_InitStructure.SPI_CRCPolynomial = 7;
+    SPI_Init(SPI1, &SPI_InitStructure);
+
+    /* SPI1 enable */
+    SPI_Cmd(SPI1, ENABLE);  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hw.h	Sat Feb 04 13:29:31 2012 +1030
@@ -0,0 +1,2 @@
+void	hw_init(void);
+
--- a/lcd.c	Sun Jan 22 17:10:51 2012 +1030
+++ b/lcd.c	Sat Feb 04 13:29:31 2012 +1030
@@ -56,28 +56,28 @@
 */
 
 #include <stdio.h>
+#include <stdint.h>
 #include "stm32f10x.h"
 #include "lcd.h"
-
-static void	LCD_Doinit(void);
+#include "delay.h"
 
 #define Bank1_LCD_C	((uint32_t)0x60000000)    /* Register Address */
 #define Bank1_LCD_D	((uint32_t)0x60020000)    /* Data Address */
 
 void
-LCD_WR_Reg(uint16_t index, uint16_t val) {
+lcd_wr_reg(uint16_t index, uint16_t val) {
     *(__IO uint16_t *)(Bank1_LCD_C) = index;
     *(__IO uint16_t *)(Bank1_LCD_D) = val;
 }
 
 uint16_t
-LCD_RD_Reg(uint16_t index) {
+lcd_rd_reg(uint16_t index) {
     *(__IO uint16_t *)(Bank1_LCD_C) = index;
     return(*(__IO uint16_t *)(Bank1_LCD_D));
 }
 
 uint16_t
-LCD_RD_Data(int first) {
+lcd_rd_data(int first) {
     uint16_t a = 0;
     if (first)
 	a = *(__IO uint16_t *) (Bank1_LCD_D); 	/* Dummy */
@@ -87,313 +87,17 @@
 }
 
 void
-LCD_WR_StartData(uint16_t x, uint16_t y) {
-    LCD_WR_Reg(0x20, x);
-    LCD_WR_Reg(0x21, y);
+lcd_wr_startdata(uint16_t x, uint16_t y) {
+    lcd_wr_reg(0x20, x);
+    lcd_wr_reg(0x21, y);
     *(__IO uint16_t *)(Bank1_LCD_C) = 0x22;	/* Start GRAM write */
 }
 
 void
-LCD_WR_Data(uint16_t val) {
+lcd_wr_data(uint16_t val) {
     *(__IO uint16_t *)(Bank1_LCD_D) = val;
 }
 
-/* This is a bit rough and ready */
-void
-Delay(__IO uint32_t nCount) {
-    __IO uint32_t i;
-    
-    for(; nCount != 0; nCount--)
-	for (i = 0; i < 3900; i++)
-	    ;
-}
-
-uint8_t
-SPI_WriteByte(uint8_t out) {
-    uint8_t in = 0; 
-
-    /* Wait until the transmit buffer is empty */
-    while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET)
-	;
-    
-    /* Send the byte  */
-    SPI_I2S_SendData(SPI1, out); 
-
-    /* Wait until a data is received */
-    while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET)
-	;
-    
-    /* Get the received data */
-    in = SPI_I2S_ReceiveData(SPI1); 
-
-    /* Return the shifted data */
-    return (in);
-}
-
-#define TP_SELECT()	GPIO_ResetBits(GPIOB, GPIO_Pin_7)
-#define TP_DESELECT()	GPIO_SetBits(GPIOB, GPIO_Pin_7)
-uint16_t
-TPRead(uint8_t type) { 
-    uint16_t x = 0;
-
-    /* Select device */
-    TP_SELECT();
-
-    /* Do conversion */
-    Delay(10);
-    SPI_WriteByte(type);
-
-    /* Read result */
-    Delay(10);
-    x = SPI_WriteByte(0x00);
-    x <<= 8;
-    x |= SPI_WriteByte(0x00);
-    Delay(10);
-
-    /* De-select device */
-    TP_DESELECT();
-
-    /* Right justify 12 bit result */
-    x = x >> 3;
-    return (x);
-}
-
-#define FL_SELECT()	GPIO_ResetBits(GPIOA, GPIO_Pin_4)
-#define FL_DESELECT()	GPIO_SetBits(GPIOA, GPIO_Pin_4)
-
-#define FL_READ		0x03
-#define FL_HSREAD	0x0b
-#define FL_32KERASE	0x52
-#define FL_64KERASE	0xd8
-#define FL_CHIPERASE	0x60
-#define FL_BYTEPROG	0x02
-#define FL_AAIWP	0xad
-#define FL_RDSR		0x05
-#define FL_EWSR		0x50
-#define FL_WRSR		0x01
-#define FL_WREN		0x06
-#define FL_WRDI		0x04
-#define FL_RDID		0x90
-#define FL_JEDECID	0x9f
-#define FL_EBSY		0x70
-#define FL_DBSY		0x80
-
-uint16_t
-FlashReadID(void) {
-    uint8_t	fac, dev;
-    
-    FL_SELECT();			/* Select device */
-
-    SPI_WriteByte(FL_RDID);		/* Send command */
-    SPI_WriteByte(0x00);		/* Send address cycles (ID data starts at 0) */
-    SPI_WriteByte(0x00);
-    SPI_WriteByte(0x00);
-    fac = SPI_WriteByte(0x00);		/* Read ID */
-    dev = SPI_WriteByte(0x00);
-  
-    FL_DESELECT();			/* De-select device */
-
-    return fac << 8 | dev;
-}
-
-uint8_t
-FlashReadStatus(void) {
-    uint8_t	status;
-    
-    FL_SELECT();			/* Select device */
-
-    SPI_WriteByte(FL_RDSR);		/* Send command */
-    SPI_WriteByte(0x00);		/* Send dummy byte for address cycle */
-    status = SPI_WriteByte(0x00);	/* Read status */
-  
-    FL_DESELECT();			/* De-select device */
-
-    return status;
-}
-
-void
-FlashWriteStatus(uint8_t status) {
-    /* Enable status write */
-    FL_SELECT();			/* Select device */
-    SPI_WriteByte(FL_EWSR);		/* Send command */
-    SPI_WriteByte(0x00);		/* Send data byte */
-    FL_DESELECT();
-
-    /* Actually write status */
-    FL_SELECT();			/* Re-select device for new command */			
-    SPI_WriteByte(FL_WRSR);		/* Send command */
-    SPI_WriteByte(status);		/* Send data byte */
-    FL_DESELECT();			/* De-select device */
-}
-
-void
-LCD_init(void) {
-    GPIO_InitTypeDef			GPIO_InitStructure;
-    SPI_InitTypeDef			SPI_InitStructure;
-    FSMC_NORSRAMInitTypeDef		FSMC_NORSRAMInitStructure;
-    FSMC_NORSRAMTimingInitTypeDef	p;
-    TIM_TimeBaseInitTypeDef		TIM_TimeBaseStructure;
-    
-    /* Enable FSMC clock */
-    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
-
-    /* Enable alternate function IO clock */
-    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
-
-    /* Enable GPIOD clock */
-    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
-
-    /* Enable GPIOD clock */
-    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
-
-    /* Configures LCD Control lines (FSMC Pins) in alternate function Push-Pull mode.
-     *
-     * PD0(D2), PD1(D3), PD4(NOE), PD5(NWE), PD7(NE1/CS), PD8(D13), PD9(D14),
-     * PD10(D15), PD11(A16/RS) PD14(D0), PD15(D1)
-     */
-    GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 |
-				   GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | 
-				   GPIO_Pin_14 | GPIO_Pin_15);
-    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
-    GPIO_Init(GPIOD, &GPIO_InitStructure);
-
-    /* PE7(D4), PE8(D5), PE9(D6), PE10(D7), PE11(D8), PE12(D9), PE13(D10),
-     * PE14(D11), PE15(D12)
-     */
-    GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | 
-				   GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
-				   GPIO_Pin_15);
-    GPIO_Init(GPIOE, &GPIO_InitStructure);
-
-    /* Configure backlight control (PD13/FSMC_A18 remapped to TIM4_CH2) */
-    /* Enable TIM4 clock */
-    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
-
-    /* Enable timer function
-     * Note source clock is SYSCLK / 2 = 36MHz
-     */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
-    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
-    GPIO_Init(GPIOD, &GPIO_InitStructure);
-
-    /* Remap TIM4_CH2 to PD13 */
-    GPIO_PinRemapConfig(GPIO_Remap_TIM4, ENABLE);
-    
-    /* Reset TIM4 */
-    TIM_DeInit(TIM4);
-
-    /* Time Base configuration */
-    TIM_TimeBaseStructure.TIM_Period = 999;
-    TIM_TimeBaseStructure.TIM_Prescaler = 0;
-    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
-    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down;
-
-    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
-
-    /* Init to full brightness */
-    lcd_setpwm(1000);
-
-    /* Enable timer */
-    TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable);
-    TIM_ARRPreloadConfig(TIM4, ENABLE);
-    TIM_Cmd(TIM4, ENABLE);
-
-    /* Configure reset pin (PE1) as GPIO out PP */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
-    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
-    GPIO_Init(GPIOE, &GPIO_InitStructure);
-
-    /* Configures the Parallel interface (FSMC) for LCD (Parallel mode) */
-    /* Timing configuration */
-    p.FSMC_AddressSetupTime = 5;
-    p.FSMC_AddressHoldTime = 5;
-    p.FSMC_DataSetupTime = 5;
-    p.FSMC_BusTurnAroundDuration = 0;
-    p.FSMC_CLKDivision = 0;
-    p.FSMC_DataLatency = 0;
-    p.FSMC_AccessMode = FSMC_AccessMode_A;
-
-    /* FSMC_Bank1_NORSRAM1 configured as follows:
-       - Data/Address MUX = Disable
-       - Memory Type = SRAM
-       - Data Width = 16bit
-       - Write Operation = Enable
-       - Extended Mode = Disable
-       - Asynchronous Wait = Disable */
-    FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
-    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
-    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
-    FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
-    FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
-    FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
-    FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
-    FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
-    FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
-    FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);  
-
-    /* Enable FSMC_Bank1_NORSRAM1 */
-    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
-
-    /* Configure touch screen controller
-     *
-     * Connected to SPI1 which is shared with the AT45DB161D.
-     *
-     * The touch screen is selected with PB7.
-     * The flash chip is selected with PA4.
-     */
-
-    /* Enable SPI1 clock */
-    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
-
-    /* Configure MOSI, MISO and SCLK as alternate function PP */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
-    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
-    GPIO_Init(GPIOA, &GPIO_InitStructure);
-
-    /* Configure flash chip select pin (PA4) as GPIO out PP */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
-    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
-    GPIO_Init(GPIOA, &GPIO_InitStructure);
-
-    /* Configure touch chip select pin (PB7) as GPIO out PP */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
-    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
-    GPIO_Init(GPIOB, &GPIO_InitStructure);
-
-    /* De-select touch & flash */
-    GPIO_SetBits(GPIOA, GPIO_Pin_4);
-    GPIO_SetBits(GPIOB, GPIO_Pin_7);
-    
-    /* SPI1 Config */
-    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
-    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
-    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
-    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
-    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
-    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
-    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
-    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
-    SPI_InitStructure.SPI_CRCPolynomial = 7;
-    SPI_Init(SPI1, &SPI_InitStructure);
-
-    /* SPI1 enable */
-    SPI_Cmd(SPI1, ENABLE);  
-
-    LCD_Doinit();
-}
-
 void
 lcd_setpwm(uint16_t val) {
     TIM_OCInitTypeDef			TIM_OCInitStructure;
@@ -408,127 +112,206 @@
 
 }
 
-static void
-LCD_Doinit(void) {
+void
+lcd_init(void) {
     uint16_t				id;
 
     /* Initialise LCD panel */
 
     /* Pull reset pin low */
-    Delay(1);
+    delay(1);
     GPIO_ResetBits(GPIOE, GPIO_Pin_1);
-    Delay(10);
+    delay(10);
     GPIO_SetBits(GPIOE, GPIO_Pin_1);
-    Delay(50);
+    delay(50);
 
-    id = LCD_RD_Reg(0x00);
+    id = lcd_rd_reg(0x00);
     if (id != 0x9325) {
 	printf("LCD ID doesn't match, expected 0x9325 got 0x%x\r\n", id);
 	return;
     }
     printf("LCD ID matches\r\n");
     
-    LCD_WR_Reg(0x00e3, 0x3008); /* Set internal timing (not documented) */
-    LCD_WR_Reg(0x00e7, 0x0012); /* Set internal timing (not documented) */
-    LCD_WR_Reg(0x00ef, 0x1231); /* Set internal timing (not documented) */
-    LCD_WR_Reg(0x0000, 0x0001); /* Start Oscillation */
-    Delay(50);
-    LCD_WR_Reg(0x0001, 0x0100); /* set SS (S720 -> S1) */
-    LCD_WR_Reg(0x0002, 0x0700); /* set line inversion (B/C + EOR) */
-    LCD_WR_Reg(0x0004, 0x0000); /* no resizing */
-    LCD_WR_Reg(0x0008, 0x0202); /* set the back porch and front porch (2 lines each) */
-    LCD_WR_Reg(0x0009, 0x0000); /* set non-display area refresh cycle ISC[3:0] */
-    LCD_WR_Reg(0x000a, 0x0000); /* FMARK function */
+    lcd_wr_reg(0x00e3, 0x3008); /* Set internal timing (not documented) */
+    lcd_wr_reg(0x00e7, 0x0012); /* Set internal timing (not documented) */
+    lcd_wr_reg(0x00ef, 0x1231); /* Set internal timing (not documented) */
+    lcd_wr_reg(0x0000, 0x0001); /* Start Oscillation */
+    delay(50);
+    lcd_wr_reg(0x0001, 0x0100); /* set SS (S720 -> S1) */
+    lcd_wr_reg(0x0002, 0x0700); /* set line inversion (B/C + EOR) */
+    lcd_wr_reg(0x0004, 0x0000); /* no resizing */
+    lcd_wr_reg(0x0008, 0x0202); /* set the back porch and front porch (2 lines each) */
+    lcd_wr_reg(0x0009, 0x0000); /* set non-display area refresh cycle ISC[3:0] */
+    lcd_wr_reg(0x000a, 0x0000); /* FMARK function */
 
-    LCD_WR_Reg(0x000c, 0x0000); /* RGB ctl - Internal clock, 18bit interface */
-    LCD_WR_Reg(0x000d, 0x0000); /* Frame marker Position */
-    LCD_WR_Reg(0x000f, 0x0000); /* RGB interface polarity */
+    lcd_wr_reg(0x000c, 0x0000); /* RGB ctl - Internal clock, 18bit interface */
+    lcd_wr_reg(0x000d, 0x0000); /* Frame marker Position */
+    lcd_wr_reg(0x000f, 0x0000); /* RGB interface polarity */
 
     /* Power On sequence  */
-    LCD_WR_Reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-    LCD_WR_Reg(0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */
-    LCD_WR_Reg(0x0012, 0x0000); /* VREG1OUT voltage */
-    LCD_WR_Reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
-    Delay(200);                 /* Dis-charge capacitor power voltage */
-    LCD_WR_Reg(0x0010, 0x1690); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-    LCD_WR_Reg(0x0011, 0x0227); /* R11h = 0x0221 at VCI = 3.3V, DC1[2:0], DC0[2:0], VC[2:0] */
-    Delay(50);                  /* Delay 50ms */
-    LCD_WR_Reg(0x0012, 0x001c); /* External reference voltage= Vci; */
-    Delay(50);                  /* Delay 50ms */
-    LCD_WR_Reg(0x0013, 0x1800); /* R13 = 1200 when R12 = 009D; VDV[4:0] for VCOM amplitude */
-    LCD_WR_Reg(0x0029, 0x001c); /* R29 = 000C when R12 = 009D; VCM[5:0] for VCOMH */
-    LCD_WR_Reg(0x002b, 0x000d); /* Frame Rate = 91Hz */
-    Delay(50);                  /* Delay 50ms */
+    lcd_wr_reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+    lcd_wr_reg(0x0011, 0x0007); /* DC1[2:0], DC0[2:0], VC[2:0] */
+    lcd_wr_reg(0x0012, 0x0000); /* VREG1OUT voltage */
+    lcd_wr_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+    delay(200);                 /* Dis-charge capacitor power voltage */
+    lcd_wr_reg(0x0010, 0x1690); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+    lcd_wr_reg(0x0011, 0x0227); /* R11h = 0x0221 at VCI = 3.3V, DC1[2:0], DC0[2:0], VC[2:0] */
+    delay(50);                  /* delay 50ms */
+    lcd_wr_reg(0x0012, 0x001c); /* External reference voltage= Vci; */
+    delay(50);                  /* delay 50ms */
+    lcd_wr_reg(0x0013, 0x1800); /* R13 = 1200 when R12 = 009D; VDV[4:0] for VCOM amplitude */
+    lcd_wr_reg(0x0029, 0x001c); /* R29 = 000C when R12 = 009D; VCM[5:0] for VCOMH */
+    lcd_wr_reg(0x002b, 0x000d); /* Frame Rate = 91Hz */
+    delay(50);                  /* delay 50ms */
 
     /* Set GRAM area */
-    LCD_WR_Reg(0x0050, 0x0000); /* Horizontal GRAM Start Address */
-    LCD_WR_Reg(0x0051, 0x00ef); /* Horizontal GRAM End Address */
-    LCD_WR_Reg(0x0052, 0x0000); /* Vertical GRAM Start Address */
-    LCD_WR_Reg(0x0053, 0x013f); /* Vertical GRAM Start Address */
+    lcd_wr_reg(0x0050, 0x0000); /* Horizontal GRAM Start Address */
+    lcd_wr_reg(0x0051, 0x00ef); /* Horizontal GRAM End Address */
+    lcd_wr_reg(0x0052, 0x0000); /* Vertical GRAM Start Address */
+    lcd_wr_reg(0x0053, 0x013f); /* Vertical GRAM Start Address */
 
-    LCD_WR_Reg(0x0060, 0xa700); /* Gate Scan Line, drive G320 -> G1 */
-    LCD_WR_Reg(0x0061, 0x0003); /* VLE & REV */
-    LCD_WR_Reg(0x006a, 0x0000); /* set scrolling line */
+    lcd_wr_reg(0x0060, 0xa700); /* Gate Scan Line, drive G320 -> G1 */
+    lcd_wr_reg(0x0061, 0x0003); /* VLE & REV */
+    lcd_wr_reg(0x006a, 0x0000); /* set scrolling line */
 
     /* Partial Display Control */
-    LCD_WR_Reg(0x0080, 0x0000); /* Image 1 */
-    LCD_WR_Reg(0x0081, 0x0000);
-    LCD_WR_Reg(0x0082, 0x0000);
-    LCD_WR_Reg(0x0083, 0x0000); /* Image 2 */
-    LCD_WR_Reg(0x0084, 0x0000);
-    LCD_WR_Reg(0x0085, 0x0000);
+    lcd_wr_reg(0x0080, 0x0000); /* Image 1 */
+    lcd_wr_reg(0x0081, 0x0000);
+    lcd_wr_reg(0x0082, 0x0000);
+    lcd_wr_reg(0x0083, 0x0000); /* Image 2 */
+    lcd_wr_reg(0x0084, 0x0000);
+    lcd_wr_reg(0x0085, 0x0000);
 
     /* Panel Control */
-    LCD_WR_Reg(0x0090, 0x0010);
-    LCD_WR_Reg(0x0092, 0x0000);
-    LCD_WR_Reg(0x0093, 0x0003);
-    LCD_WR_Reg(0x0095, 0x0110);
-    LCD_WR_Reg(0x0097, 0x0000); /* Undocumented */
-    LCD_WR_Reg(0x0098, 0x0000); /* Undocumented */
+    lcd_wr_reg(0x0090, 0x0010);
+    lcd_wr_reg(0x0092, 0x0000);
+    lcd_wr_reg(0x0093, 0x0003);
+    lcd_wr_reg(0x0095, 0x0110);
+    lcd_wr_reg(0x0097, 0x0000); /* Undocumented */
+    lcd_wr_reg(0x0098, 0x0000); /* Undocumented */
 
-    LCD_WR_Reg(0x0007, 0x0133); /* Display on, 262k colour mode (vs 8) */
+    lcd_wr_reg(0x0007, 0x0133); /* Display on, 262k colour mode (vs 8) */
 
-    LCD_WR_Reg(0x0003, 0x1030); /* set GRAM write direction and enable BGR, 64K colours, 1 transfers/pixel. */
+    lcd_wr_reg(0x0003, 0x1030); /* set GRAM write direction and enable BGR, 64K colours, 1 transfers/pixel. */
 
     /* Adjust the Gamma Curve */
-    LCD_WR_Reg(0x0030, 0x0006);
-    LCD_WR_Reg(0x0031, 0x0101);
-    LCD_WR_Reg(0x0032, 0x0003);
-    LCD_WR_Reg(0x0035, 0x0106);
-    LCD_WR_Reg(0x0036, 0x0b02);
-    LCD_WR_Reg(0x0037, 0x0302);
-    LCD_WR_Reg(0x0038, 0x0707);
-    LCD_WR_Reg(0x0039, 0x0007);
-    LCD_WR_Reg(0x003c, 0x0600);
-    LCD_WR_Reg(0x003d, 0x020b);
+    lcd_wr_reg(0x0030, 0x0006);
+    lcd_wr_reg(0x0031, 0x0101);
+    lcd_wr_reg(0x0032, 0x0003);
+    lcd_wr_reg(0x0035, 0x0106);
+    lcd_wr_reg(0x0036, 0x0b02);
+    lcd_wr_reg(0x0037, 0x0302);
+    lcd_wr_reg(0x0038, 0x0707);
+    lcd_wr_reg(0x0039, 0x0007);
+    lcd_wr_reg(0x003c, 0x0600);
+    lcd_wr_reg(0x003d, 0x020b);
 
     fputs("Testing\r\n", stdout);
-    LCD_WR_StartData(0, 0);
-    LCD_WR_Data(0xa5a5);
-    LCD_WR_Data(0x5a5a);
-    LCD_WR_StartData(0, 0);
-    if ((id = LCD_RD_Data(1)) != 0xa5a5)
+    lcd_wr_startdata(0, 0);
+    lcd_wr_data(0xa5a5);
+    lcd_wr_data(0x5a5a);
+    lcd_wr_startdata(0, 0);
+    if ((id = lcd_rd_data(1)) != 0xa5a5)
 	printf("Expected 0xa5a5 got 0x%04x\r\n", id);
     
-    if ((id = LCD_RD_Data(0)) != 0x5a5a)
+    if ((id = lcd_rd_data(0)) != 0x5a5a)
 	printf("Expected 0x5a5a got 0x%04x\r\n", id);
 
     fputs("Filling\r\n", stdout);
     /* Fill panel */
-    LCD_WR_StartData(0, 0);
-
-#define RGB24_565(R, G, B) (((((R) >> 3) & 0x1f) << 11) | ((((G) >> 2) & 0x3f) << 5) | (((B) >> 3) & 0x1f))
+    lcd_wr_startdata(0, 0);
 
     for (int x = 0; x < 320; x++) {
 	for (int y = 0; y < 240; y++) {
 	    if (((x / 5) % 3) == 0)
-		LCD_WR_Data(RGB24_565(255, 0, 0));
+		lcd_wr_data(LCD_RED);
 	    else if (((x / 5) % 3) == 1)
-		LCD_WR_Data(RGB24_565(0, 255, 0));
+		lcd_wr_data(LCD_GREEN);
 	    else
-		LCD_WR_Data(RGB24_565(0, 0, 255));
+		lcd_wr_data(LCD_BLUE);
 	}
     }
 
+    lcd_circle(50, 50, 20, LCD_BLACK);
+
+}
+
+void
+lcd_pixel(uint16_t x, uint16_t y, uint16_t colour) {
+    if (x > LCD_HEIGHT || y > LCD_WIDTH)
+	return;
+
+    lcd_wr_startdata(x, y);
+    lcd_wr_data(colour);
 }
 
+/* 
+ * Draw a circle
+ * From http://en.wikipedia.org/wiki/Midpoint_circle_algorithm 
+ */
+void
+lcd_circle(uint16_t x0, uint16_t y0, uint16_t radius, uint16_t colour) {
+    int16_t	f;
+    uint16_t	ddF_x, ddF_y, x, y;
+    
+    f = 1 - radius;
+    ddF_x = 1;
+    ddF_y = -2 * radius;
+    x = 0;
+    y = radius;
+ 
+    lcd_pixel(x0, y0 + radius, colour);
+    lcd_pixel(x0, y0 - radius, colour);
+    lcd_pixel(x0 + radius, y0, colour);
+    lcd_pixel(x0 - radius, y0, colour);
+ 
+    while(x < y) {
+	// ddF_x == 2 * x + 1;
+	// ddF_y == -2 * y;
+	// f == x*x + y*y - radius*radius + 2*x - y + 1;
+	if(f >= 0) {
+	    y--;
+	    ddF_y += 2;
+	    f += ddF_y;
+	}
+	x++;
+	ddF_x += 2;
+	f += ddF_x;    
+	lcd_pixel(x0 + x, y0 + y, colour);
+	lcd_pixel(x0 - x, y0 + y, colour);
+	lcd_pixel(x0 + x, y0 - y, colour);
+	lcd_pixel(x0 - x, y0 - y, colour);
+	lcd_pixel(x0 + y, y0 + x, colour);
+	lcd_pixel(x0 - y, y0 + x, colour);
+	lcd_pixel(x0 + y, y0 - x, colour);
+	lcd_pixel(x0 - y, y0 - x, colour);
+    }
+}
+
+
+/*
+ * Draw a line
+ * From http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
+ */
+void
+lcd_line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t colour) {
+    uint16_t dx, dy, d, x, y;
+
+    dx = x1 - x0;
+    dy = y1 - y0;
+    
+    d = 2 * dy - dx;
+    lcd_pixel(x0, y0, colour);
+    y = y0;
+    
+    for (x = x0 + 1; x <= x1; x++) {
+	if (d > 0) {
+	    y++;
+	    lcd_pixel(x, y, colour);
+	    d += 2 * dy - 2 * dx;
+	} else {
+	    lcd_pixel(x, y, colour);
+	    d += 2 * dy;
+	}
+    }
+}
--- a/lcd.h	Sun Jan 22 17:10:51 2012 +1030
+++ b/lcd.h	Sat Feb 04 13:29:31 2012 +1030
@@ -1,57 +1,20 @@
-#ifndef LCD_H_
-#define LCD_H_
-
-void		LCD_init(void);
-void		LCD_WR_Reg(uint16_t index, uint16_t val);
-uint16_t	LCD_RD_Reg(uint16_t index);
-uint16_t	LCD_RD_Data(int first);
-void		LCD_WR_Data(uint16_t val);
-void		LCD_WR_StartData(uint16_t x, uint16_t y);
-void		Delay(__IO uint32_t nCount);
-
-/* Touch controller (TSC2046N) defines */
-/* Mode/channel select defines */
-#define TP_READ_SEL(chan, mode, ref, pd) (0x80 | (((chan) & 0x07) << 4) | (((mode) & 0x01) << 3) | (((ref) & 0x01) << 2) | ((pd) & 0x03))
-
-/* Channel select */
-#define TP_CHAN_TEMP0	0
-#define TP_CHAN_Y	1	
-#define TP_CHAN_VBAT	2
-#define TP_CHAN_Z1	3
-#define TP_CHAN_Z2	4
-#define TP_CHAN_X	5
-#define TP_CHAN_AUX	6
-#define TP_CHAN_TEMP1	7
-
-/* Mode select */
-#define TP_MODE_12	0
-#define TP_MODE_8	1
+void		lcd_init(void);
+void		lcd_wr_reg(uint16_t index, uint16_t val);
+uint16_t	lcd_rd_reg(uint16_t index);
+uint16_t	lcd_rd_data(int first);
+void		lcd_wr_data(uint16_t val);
+void		lcd_wr_startdata(uint16_t x, uint16_t y);
+void		lcd_setpwm(uint16_t val);
+void		lcd_pixel(uint16_t x, uint16_t y, uint16_t colour);
+void		lcd_circle(uint16_t x0, uint16_t y0, uint16_t radius, uint16_t colour);
+void		lcd_line(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t colour);
 
-/* Reference type */
-#define TP_REF_DIFF	0
-#define TP_REF_SER	1
-
-/* Power down mode */
-#define TP_PD_AUTO	0
-#define TP_PD_REF_OFF	1
-#define TP_PD_REF_ON	2
-#define TP_PD_ON	3
-
-uint16_t	TPRead(uint8_t type);
+#define LCD_HEIGHT	240
+#define LCD_WIDTH	320
 
-uint16_t	FlashReadID(void);
-uint8_t		FlashReadStatus(void);
-
-#define FL_BP0	(1<<2)
-#define FL_BP1	(1<<3)
-#define FL_BP2	(1<<4)
-#define FL_BP3	(1<<5)
-#define FL_BPL	(1<<7)
-void		FlashWriteStatus(uint8_t status);
-
-void		FlashWriteCtl(int enable);
-
-void		lcd_setpwm(uint16_t val);
-
-#endif
-
+#define RGB24_565(R, G, B) (((((R) >> 3) & 0x1f) << 11) | ((((G) >> 2) & 0x3f) << 5) | (((B) >> 3) & 0x1f))
+#define LCD_WHITE	RGB24_565(255, 255, 255)
+#define LCD_BLACK	RGB24_565(0, 0, 0)
+#define LCD_RED		RGB24_565(255, 0, 0)
+#define LCD_GREEN	RGB24_565(0, 255, 0)
+#define LCD_BLUE	RGB24_565(0, 0, 255)
--- a/main.c	Sun Jan 22 17:10:51 2012 +1030
+++ b/main.c	Sat Feb 04 13:29:31 2012 +1030
@@ -8,9 +8,14 @@
 #include <stdlib.h>
 
 #include "stm32f10x.h"
+
+#include "comm.h"
+#include "delay.h"
+#include "flash.h"
+#include "hw.h"
 #include "lcd.h"
 #include "main.h"
-#include "comm.h"
+#include "touch.h"
 
 typedef struct {
     char		buf[40];
@@ -18,7 +23,6 @@
     uint8_t		len;
 } consbuf_t;
 
-void Setup_HW(void);
 void NVIC_Configuration(void);
 
 
@@ -105,8 +109,8 @@
     
     cmd.state = cmd.len = 0;
     
-    /* Setup USART etc */
-    Setup_HW();
+    /* Init hardware - configure IO ports and external peripherals */
+    hw_init();
 
     /* NVIC configuration */
     NVIC_Configuration();
@@ -119,9 +123,6 @@
 	    ;
     }
 
-    /* Init LCD panel */
-    LCD_init();
-
     /* Set stdout to unbuffered */
     setvbuf(stdout, NULL, _IONBF, 0);
     
@@ -148,16 +149,10 @@
 	    } else if (!strncmp("read", cmd.buf, 4)) {
 		printf("PB5 = %d\r\n", GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_15));
 	    } else if (!strncmp("touch", cmd.buf, 5)) {
+		uint16_t	x, y, z1, z2;
+		float		t, t2;
 		for (int i = 0; i < 10; i++) {
-		    uint16_t	x, y, z1, z2;
-		    float	t, t2;
-		    
-		    x = TPRead(TP_READ_SEL(TP_CHAN_X, TP_MODE_12, TP_REF_DIFF, TP_PD_ON));
-		    y = TPRead(TP_READ_SEL(TP_CHAN_Y, TP_MODE_12, TP_REF_DIFF, TP_PD_ON));
-		    z1 = TPRead(TP_READ_SEL(TP_CHAN_Z1, TP_MODE_12, TP_REF_DIFF, TP_PD_ON));
-		    z2 = TPRead(TP_READ_SEL(TP_CHAN_Z2, TP_MODE_12, TP_REF_DIFF, TP_PD_ON));
-		    t = ((float)x / 4096.0) * (((float)z2 / (float)z1) - 1);
-		    t2 = (((float)x / 4096) * ((4096.0 / (float)z1) - 1)) - (1 - ((float)y / (float)4096.0));
+		    tp_getcoords(&x, &y, &z1, &z2, &t, &t2);
 		    printf("X = %5d Y = %5d Z1 = %5d Z2 = %5d T = %7.2f T2 = %7.2f\r\n", x, y, z1, z2, t, t2);
 		}
 	    } else if (!strncmp("fl", cmd.buf, 2)) {
@@ -173,8 +168,8 @@
 		    "BPL"
 		};
 		
-		printf("Flash ID = 0x%04hx (expect 0xbf41)\r\n", FlashReadID());
-		status = FlashReadStatus();
+		printf("Flash ID = 0x%04hx (expect 0xbf41)\r\n", flashreadid());
+		status = flashreadstatus();
 
 		fputs("Status = ", stdout);
 		for (unsigned int i = 0; i < sizeof(flstattbl) / sizeof(flstattbl[0]); i++)
@@ -184,9 +179,9 @@
 		    }
 		printf("(0x%02x)\r\n", status);
 
-		FlashWriteStatus(0x00);
+		flashwritestatus(0x00);
 		
-		status = FlashReadStatus();
+		status = flashreadstatus();
 
 		fputs("Status = ", stdout);
 		for (unsigned int i = 0; i < sizeof(flstattbl) / sizeof(flstattbl[0]); i++)
@@ -199,112 +194,40 @@
 		lcd_setpwm(atoi(cmd.buf + 4));
 	    } else if (!strncmp("timing", cmd.buf, 6)) {
 		fputs("Timing..\r\n", stdout);
-		Delay(10000);
+		delay(10000);
 		fputs("Done\r\n", stdout);
+	    } else if (!strncmp("circ ", cmd.buf, 5)) {
+		uint16_t	x, y, r, c;
+		char		col;
+		
+		if (sscanf(cmd.buf, "circ %hu %hu %hu %c", &x, &y, &r, &col) != 4) {
+		    printf("Unable to parse circ args\r\n");
+		    goto out;
+		}
+
+		col = toupper(col);
+		if (col == 'R')
+		    c = LCD_RED;
+		else if (col == 'G')
+		    c = LCD_GREEN;
+		else if (col == 'B')
+		    c = LCD_BLUE;
+		else if (col == 'L')
+		    c = LCD_BLACK;
+		else
+		    c = LCD_WHITE;
+		lcd_circle(x, y, r, c);
 	    } else if (!strncmp("zz", cmd.buf, 2)) {
 		NVIC_SystemReset();
 	    } else {
 		printf("Unknown command\r\n");
 	    }
 	}
+      out:
 	cmd.state = 0;
     }
 }
 
-/* Setup hardware (USART etc) */
-void
-Setup_HW(void) {
-    GPIO_InitTypeDef GPIO_InitStructure;
-    USART_InitTypeDef USART_InitStructure;
-
-    /* RTC stuff */
-    /* Enable PWR and BKP clocks */
-    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
-
-    /* Allow access to BKP Domain */
-    PWR_BackupAccessCmd(ENABLE);
-
-    /* Reset Backup Domain
-     *
-     * This resets the RTC etc back to 0 so probably only useful under user command
-     BKP_DeInit();
-    */
-
-    /* Enable Low Speed External clock */
-    RCC_LSEConfig(RCC_LSE_ON);
-
-    /* Wait till LSE is ready */
-    while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
-	;
-
-    /* Select LSE as RTC Clock Source */
-    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
-
-    /* Enable RTC Clock */
-    RCC_RTCCLKCmd(ENABLE);
-
-    /* Wait for RTC registers synchronization */
-    RTC_WaitForSynchro();
-
-    /* Wait until last write operation on RTC registers has finished */
-    RTC_WaitForLastTask();
-
-    /* Wait until last write operation on RTC registers has finished */
-    RTC_WaitForLastTask();
-
-    /* Set RTC prescaler: set RTC period to 1sec */
-    RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */
-
-    /* Wait until last write operation on RTC registers has finished */
-    RTC_WaitForLastTask();
-
-    /* Clock setup */
-    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
-
-    /* Port configuration */
-    /* Configure USART1 TX (PA.09) as alternate function push-pull */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
-    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
-    GPIO_Init(GPIOA, &GPIO_InitStructure);
-
-    /* Configure USART1 RX (PA.10) as input floating */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
-    GPIO_Init(GPIOA, &GPIO_InitStructure);
-
-    /* Enable GPIOB clock */
-    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
-
-    /* Configure PB5 as output push-pull for LED */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
-    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
-    GPIO_Init(GPIOB, &GPIO_InitStructure);
-
-    /* Configure PB15 as input pull-up push-pull for push button */
-    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
-    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
-    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
-    GPIO_Init(GPIOB, &GPIO_InitStructure);
-
-    /* USART configuration */
-    /* USART1 - 115200 8n1, no flow control TX & RX enabled */
-    USART_InitStructure.USART_BaudRate = 115200;
-    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
-    USART_InitStructure.USART_StopBits = USART_StopBits_1;
-    USART_InitStructure.USART_Parity = USART_Parity_No;
-    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
-    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
-    USART_Init(USART1, &USART_InitStructure);
-
-    /* Enable interrupts on receive data */
-    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
-
-    /* Enable USART */
-    USART_Cmd(USART1, ENABLE);
-}
-
 /* Configure interrupt controller */
 #ifdef VECT_TAB_RAM
 /* vector-offset (TBLOFF) from bottom of SRAM. defined in linker script */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spi.c	Sat Feb 04 13:29:31 2012 +1030
@@ -0,0 +1,26 @@
+#include <stdint.h>
+#include "spi.h"
+#include "stm32f10x.h"
+
+uint8_t
+SPI_WriteByte(uint8_t out) {
+    uint8_t in = 0; 
+
+    /* Wait until the transmit buffer is empty */
+    while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET)
+	;
+    
+    /* Send the byte  */
+    SPI_I2S_SendData(SPI1, out); 
+
+    /* Wait until a data is received */
+    while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET)
+	;
+    
+    /* Get the received data */
+    in = SPI_I2S_ReceiveData(SPI1); 
+
+    /* Return the shifted data */
+    return (in);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/spi.h	Sat Feb 04 13:29:31 2012 +1030
@@ -0,0 +1,2 @@
+uint8_t		SPI_WriteByte(uint8_t out);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/touch.c	Sat Feb 04 13:29:31 2012 +1030
@@ -0,0 +1,45 @@
+#include <stdint.h>
+
+#include "stm32f10x.h"
+#include "delay.h"
+#include "spi.h"
+#include "touch.h"
+
+#define TP_SELECT()	GPIO_ResetBits(GPIOB, GPIO_Pin_7)
+#define TP_DESELECT()	GPIO_SetBits(GPIOB, GPIO_Pin_7)
+
+uint16_t
+tp_read(uint8_t type) { 
+    uint16_t x = 0;
+
+    /* Select device */
+    TP_SELECT();
+
+    /* Do conversion */
+    delay(10);
+    SPI_WriteByte(type);
+
+    /* Read result */
+    delay(10);
+    x = SPI_WriteByte(0x00);
+    x <<= 8;
+    x |= SPI_WriteByte(0x00);
+    delay(10);
+
+    /* De-select device */
+    TP_DESELECT();
+
+    /* Right justify 12 bit result */
+    x = x >> 3;
+    return (x);
+}
+
+void
+tp_getcoords(uint16_t *x, uint16_t *y, uint16_t *z1, uint16_t *z2, float *t, float *t2) {
+    *x = tp_read(TP_READ_SEL(TP_CHAN_X, TP_MODE_12, TP_REF_DIFF, TP_PD_ON));
+    *y = tp_read(TP_READ_SEL(TP_CHAN_Y, TP_MODE_12, TP_REF_DIFF, TP_PD_ON));
+    *z1 = tp_read(TP_READ_SEL(TP_CHAN_Z1, TP_MODE_12, TP_REF_DIFF, TP_PD_ON));
+    *z2 = tp_read(TP_READ_SEL(TP_CHAN_Z2, TP_MODE_12, TP_REF_DIFF, TP_PD_ON));
+    *t = ((float)*x / 4096.0) * (((float)*z2 / (float)*z1) - 1);
+    *t2 = (((float)*x / 4096) * ((4096.0 / (float)*z1) - 1)) - (1 - ((float)*y / (float)4096.0));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/touch.h	Sat Feb 04 13:29:31 2012 +1030
@@ -0,0 +1,31 @@
+/* Touch controller (TSC2046N) defines */
+/* Mode/channel select defines */
+#define TP_READ_SEL(chan, mode, ref, pd) (0x80 | (((chan) & 0x07) << 4) | (((mode) & 0x01) << 3) | (((ref) & 0x01) << 2) | ((pd) & 0x03))
+
+/* Channel select */
+#define TP_CHAN_TEMP0	0
+#define TP_CHAN_Y	1	
+#define TP_CHAN_VBAT	2
+#define TP_CHAN_Z1	3
+#define TP_CHAN_Z2	4
+#define TP_CHAN_X	5
+#define TP_CHAN_AUX	6
+#define TP_CHAN_TEMP1	7
+
+/* Mode select */
+#define TP_MODE_12	0
+#define TP_MODE_8	1
+
+/* Reference type */
+#define TP_REF_DIFF	0
+#define TP_REF_SER	1
+
+/* Power down mode */
+#define TP_PD_AUTO	0
+#define TP_PD_REF_OFF	1
+#define TP_PD_REF_ON	2
+#define TP_PD_ON	3
+
+uint16_t	tp_read(uint8_t type);
+void		tp_getcoords(uint16_t *x, uint16_t *y, uint16_t *z1, uint16_t *z2, float *t, float *t2);
+