diff options
Diffstat (limited to 'example-primer2/primer2-ts.c')
-rw-r--r-- | example-primer2/primer2-ts.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/example-primer2/primer2-ts.c b/example-primer2/primer2-ts.c new file mode 100644 index 0000000..eb1c4ec --- /dev/null +++ b/example-primer2/primer2-ts.c @@ -0,0 +1,223 @@ +#include <stdint.h> +#include <stdlib.h> +#include <chopstx.h> +#include "stm32f103.h" +#include "st7732.h" +#include "primer2-ts.h" + +/* ADC3 routines. */ + +#define ADC3_BASE (APB2PERIPH_BASE + 0x3c00) +static struct ADC *const ADC3 = (struct ADC *const)ADC3_BASE; + +#define RCC_APB2ENR_ADC3EN 0x8000 +#define RCC_APB2RSTR_ADC3RST 0x8000 + +#define ADC_SR_JEOC 0x0004 + +#define ADC_CR1_JEOCIE (1 << 7) + +#define ADC_CR2_JSWSTART (1 << 21) +#define ADC_CR2_JEXTTRIG (1 << 15) +#define ADC_CR2_JEXTSEL(n) ((n) << 12) + +#define ADC_JSQR_NUM_CH(n) (((n) - 1) << 20) +#define ADC_JSQR_JSQ1_N(n) ((n) << 0) +#define ADC_JSQR_JSQ2_N(n) ((n) << 5) +#define ADC_JSQR_JSQ3_N(n) ((n) << 10) +#define ADC_JSQR_JSQ4_N(n) ((n) << 15) + +#define ADC_CHANNEL_IN10 10 +#define ADC_CHANNEL_IN11 11 +#define ADC_CHANNEL_IN12 12 +#define ADC_CHANNEL_IN13 13 + +#define USE_ADC3_INTR 1 +#define INTR_REQ_ADC3 47 + +/* + * Do calibration for ADC3. + */ +void adc3_init (void) +{ + RCC->APB2ENR |= RCC_APB2ENR_ADC3EN; + RCC->APB2RSTR = RCC_APB2RSTR_ADC3RST; + RCC->APB2RSTR = 0; + + ADC3->CR1 = 0; + ADC3->CR2 = ADC_CR2_ADON; + ADC3->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL; + while ((ADC3->CR2 & ADC_CR2_RSTCAL) != 0) + ; + ADC3->CR2 = ADC_CR2_ADON | ADC_CR2_CAL; + while ((ADC3->CR2 & ADC_CR2_CAL) != 0) + ; + ADC3->CR2 = 0; + RCC->APB2ENR &= ~RCC_APB2ENR_ADC3EN; +} + +static chopstx_intr_t adc3_intr; + +void +adc3_start (void) +{ + RCC->APB2ENR |= RCC_APB2ENR_ADC3EN; + +#if USE_ADC3_INTR + ADC3->CR1 = ADC_CR1_SCAN | ADC_CR1_JEOCIE; +#else + ADC3->CR1 = ADC_CR1_SCAN; +#endif + ADC3->CR2 = ADC_CR2_JEXTTRIG | ADC_CR2_JEXTSEL(7) | ADC_CR2_ADON; + ADC3->SMPR1 = 0xfff; + ADC3->SMPR2 = 0; + ADC3->JSQR = (ADC_JSQR_NUM_CH(4) | ADC_JSQR_JSQ4_N(ADC_CHANNEL_IN13) + | ADC_JSQR_JSQ3_N(ADC_CHANNEL_IN12) + | ADC_JSQR_JSQ2_N(ADC_CHANNEL_IN11) + | ADC_JSQR_JSQ1_N(ADC_CHANNEL_IN10)); + +#if USE_ADC3_INTR + chopstx_claim_irq (&adc3_intr, INTR_REQ_ADC3); +#endif +} + +void adc3_conversion (uint32_t *result) +{ + + /* Start conversion. */ + ADC3->CR2 |= ADC_CR2_JSWSTART; + +#if USE_ADC3_INTR + chopstx_intr_wait (&adc3_intr); +#else + while (1) + { + chopstx_usec_wait (1000); + if (ADC3->SR & ADC_SR_JEOC) + break; + } +#endif + ADC3->SR &= ~ADC_SR_JEOC; + + result[0] = ADC3->JDR1; + result[1] = ADC3->JDR2; + result[2] = ADC3->JDR3; + result[3] = ADC3->JDR4; + + /* Stop conversion. */ + ADC3->CR2 &= ~ADC_CR2_JSWSTART; + + return; +} + +void adc3_stop (void) +{ + +#if USE_ADC3_INTR + chopstx_release_irq (&adc3_intr); +#endif + + /* Power off. */ + ADC3->CR1 = 0; + ADC3->CR2 = 0; + + RCC->APB2ENR &= ~RCC_APB2ENR_ADC3EN; +} + +/* Touch screen routines. */ + +int +ts_pushed (uint32_t u) +{ + return (u < 0xc00); +} + +#define FILTER_SIZE 8 + +static void +ts_filter (int buf[FILTER_SIZE][2], int result[2]) +{ + int s0, s1; + int i; + + s0 = 0; + s1 = 0; + for (i = 0; i < FILTER_SIZE; i++) + { + s0 += buf[i][0]; + s1 += buf[i][1]; + } + + result[0] = s0/FILTER_SIZE; + result[1] = s1/FILTER_SIZE; +} + +/* Simple model of primer2 touch screen: + Vdd-[R1]-[Ry]-[Rp]-[Rx]-Vss + U D l R + where R1=1k external register, Rx(resp. Ry)=resisitive component on + X(resp. Y) film and Rp=resisitive component of contact point. + Convert [L, R, U, D] to [Rx, Ry, Rp]. */ +void +ts_conversion (uint32_t a[], int r[]) +{ + int l, u, d, ir1; + int x, y, rp; + + l = a[0] & 0xfff; + u = a[2] & 0xfff; + d = a[3] & 0xfff; + ir1 = 4096 - u; + /* r1 = 1000 */ + x = (1000 * l)/ir1; + y = (1000 * (u - d))/ir1; + rp = (1000 * (d - l))/ir1; + r[0] = x; + r[1] = y; + r[2] = rp; +} + +int +ts_adjust (int *r, int *cord) +{ + int x, y; + static int buf[FILTER_SIZE][2]; + static int i = 0; + static int fill = 0; + + if (!r) + { + i = 0; + fill = 0; + return 0; + } + + /* TODO: We might need calibration. */ + x = (LCD_COLUMN * (r[0] - 0x20))/0x100; + y = (LCD_ROW * (0x1e0 - r[1]))/0x1c0; + + if (x < 0) + x = 0; + if (x >= LCD_COLUMN) + x = LCD_COLUMN - 1; + if (y < 0) + y = 0; + if (y >= LCD_ROW) + y = LCD_ROW - 1; + + buf[i][0] = x; + buf[i][1] = y; + + i++; + if (i >= FILTER_SIZE) + { + i = 0; + fill = 1; + } + + if (!fill) + return 0; + + ts_filter (buf, cord); + return 1; +} |