From df1cf45e98857e8627e9e049e58cc60679465e0d Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Tue, 18 Mar 2025 11:42:22 +0100 Subject: [PATCH] touch: add build support + proper driver/world-switch support --- CMakeLists.txt | 5 ++ include/gint/defs/util.h | 6 -- include/gint/drivers/states.h | 10 +++ include/gint/mpu/intc.h | 2 +- include/gint/touch.h | 1 - src/touch/adconv.c | 3 + src/touch/i2c.c | 123 ++++++++++++++++++++++------------ src/touch/i2c.h | 27 ++++++-- src/touch/touch.c | 89 ++++++++++++++++++++++++ 9 files changed, 213 insertions(+), 53 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd0176a..8a1f9b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,6 +253,11 @@ set(SOURCES src/usb/write4.S # Video driver interface src/video/video.c + # Touch-screen driver + src/touch/i2c.c + src/touch/i2c_inth.c + src/touch/adconv.c + src/touch/touch.c ) set(ASSETS_FX src/font5x7.png src/gdb/icons-i1msb.png) diff --git a/include/gint/defs/util.h b/include/gint/defs/util.h index 6debcc1..680a265 100644 --- a/include/gint/defs/util.h +++ b/include/gint/defs/util.h @@ -47,10 +47,4 @@ using std::max; (b) = _tmp; \ }) -/* abs() - absolute value of a variable (be careful of neg overflow) */ -#define abs(a) ({ \ - GAUTOTYPE _a = (a); \ - (_a < 0) ? -(_a) : _a; \ -}) - #endif /* GINT_DEFS_UTIL */ diff --git a/include/gint/drivers/states.h b/include/gint/drivers/states.h index d18e36a..84ec3fd 100644 --- a/include/gint/drivers/states.h +++ b/include/gint/drivers/states.h @@ -109,6 +109,16 @@ typedef struct { } usb_state_t; +/* Touch-screen modules */ +typedef struct { + uint16_t PRCR; + uint16_t PJCR; + uint8_t ICCR; + uint8_t ICIC; + uint8_t ICCL; + uint8_t ICCH; +} touch_state_t; + #ifdef __cplusplus } #endif diff --git a/include/gint/mpu/intc.h b/include/gint/mpu/intc.h index 7ccb06a..be4e0ca 100644 --- a/include/gint/mpu/intc.h +++ b/include/gint/mpu/intc.h @@ -192,7 +192,7 @@ typedef volatile struct uint16_t _MSIOF0:4; /* SH7724: Sync SCIF channel 0 */ uint16_t _MSIOF1:4; /* SH7724: Sync SCIF channel 1 */ uint16_t _1 :4; /* Unknown (TODO) */ - uint16_t _2 :4; /* Unknown (TODO) */ + uint16_t I2C:4; /* I2C */ ); pad(2); diff --git a/include/gint/touch.h b/include/gint/touch.h index eecfbb5..1ed5d21 100644 --- a/include/gint/touch.h +++ b/include/gint/touch.h @@ -10,7 +10,6 @@ extern "C" { /* touch_calib - tounch-screen calibration information */ typedef struct { - int scan_freq_us; int x_mul; int x_div; int y_mul; diff --git a/src/touch/adconv.c b/src/touch/adconv.c index 6a9b283..08585a8 100644 --- a/src/touch/adconv.c +++ b/src/touch/adconv.c @@ -1,6 +1,8 @@ //--- // gint:touchscreen:adconv - 0x84 register data conversion //--- +#include + #include #include "./adconv.h" @@ -11,6 +13,7 @@ //--- /* _adconv_check_dual() - check if it is dual or single */ +// fixme : atomic static int _adconv_check_dual( struct _touch_adconv *adconv, struct _touch_adraw *adraw diff --git a/src/touch/i2c.c b/src/touch/i2c.c index 8d3b9a6..5728e77 100644 --- a/src/touch/i2c.c +++ b/src/touch/i2c.c @@ -1,6 +1,8 @@ //--- // gint:touchscreen:i2c - I2C driver //--- +#include + #include #include #include @@ -74,47 +76,6 @@ static int _i2c_request_await(void) // Public //--- -/* i2c_power_on() - power on the I2C peripheral and install handlers */ -void i2c_power_on(void) -{ - volatile uint16_t *INTC_IPRH = (void*)0xa408001c; - volatile uint8_t *INTC_IMCR7 = (void*)0xa40800dc; - volatile uint8_t *INTC_IMR7 = (void*)0xa408009c; - volatile uint16_t *PFC_PJCR = (void*)0xa4050110; - volatile uint32_t *MSTPCR2 = (void*)0xa4150038; - extern void i2c_inth_tack(void); - extern void i2c_inth_wait(void); - extern void i2c_inth_trans(void); - extern void i2c_inth_al(void); - - // force-mask I2C interrupts - *INTC_IPRH &= 0xfff0; - *INTC_IMR7 |= 0xf0; - - // install I2C handler - intc_handler_function(0xe00, GINT_CALL(i2c_inth_al)); - intc_handler_function(0xe20, GINT_CALL(i2c_inth_tack)); - intc_handler_function(0xe40, GINT_CALL(i2c_inth_wait)); - intc_handler_function(0xe60, GINT_CALL(i2c_inth_trans)); - - // power-on I2C module - *MSTPCR2 &= 0xfffff7ff; - - // configure I2C PIN - *PFC_PJCR &= 0xf0ff; - - // configure I2C module - SH7305_I2C.ICCR.byte &= 0x7f; - SH7305_I2C.ICSR.byte = 0x00; - SH7305_I2C.ICIC.byte = 0x00; - - // Enable interrupt - *INTC_IPRH |= 1; - *INTC_IMCR7 |= 0xf0; -} - -// user API - /* i2c_reg_select() - select a register */ int i2c_reg_select(int reg) { @@ -184,3 +145,83 @@ int i2c_read_stream(void *buffer, size_t size) _i2c_hw_start_operation(); return _i2c_request_await(); } + +//--- +// Driver and state management +//--- + +#include +#include +#include + +/* i2c_hpowered() - check if the module is powered */ +bool i2c_hpowered(void) +{ + return (SH7305_POWER.MSTPCR2.I2C == 0); +} + +/* i2c_hpoweron() - power on the module */ +void i2c_hpoweron(void) +{ + SH7305_POWER.MSTPCR2.I2C = 0; + SH7305_I2C.ICCR.ICE = 0; + SH7305_I2C.ICDR = 0; +} + +/* i2c_hpoweroff() - power on the module */ +void i2c_hpoweroff(void) +{ + SH7305_POWER.MSTPCR2.I2C = 1; +} + +/* i2c_hsave() - save hardware information */ +void i2c_hsave(touch_state_t *state) +{ + state->PJCR = SH7305_PFC.PJCR.word; + state->ICCR = SH7305_I2C.ICCR.byte; + state->ICIC = SH7305_I2C.ICIC.byte; + state->ICCL = SH7305_I2C.ICCL; + state->ICCH = SH7305_I2C.ICCH; +} + +/* i2c_hrestore() - restore hardware information */ +void i2c_hrestore(touch_state_t *state) +{ + SH7305_I2C.ICCH = state->ICCH; + SH7305_I2C.ICCL = state->ICCL; + SH7305_I2C.ICIC.byte = state->ICIC; + SH7305_I2C.ICCR.byte = state->ICCR; + SH7305_PFC.PJCR.word = state->PJCR; +} + +/* i2c_configure() - configure and install interrupt handlers */ +void i2c_configure(void) +{ + extern void i2c_inth_tack(void); + extern void i2c_inth_wait(void); + extern void i2c_inth_trans(void); + extern void i2c_inth_al(void); + + // install I2C handler + intc_handler_function(0xe00, GINT_CALL(i2c_inth_al)); + intc_handler_function(0xe20, GINT_CALL(i2c_inth_tack)); + intc_handler_function(0xe40, GINT_CALL(i2c_inth_wait)); + intc_handler_function(0xe60, GINT_CALL(i2c_inth_trans)); + + // configure I2C PIN + SH7305_PFC.PJCR.P5MD = 0b00; + SH7305_PFC.PJCR.P4MD = 0b00; + + // configure I2C module + SH7305_I2C.ICCR.byte &= 0x7f; + SH7305_I2C.ICSR.byte = 0x00; + SH7305_I2C.ICIC.byte = 0x00; + + // init high-level driver information + memset((void*)&__i2c_request, 0x00, sizeof(struct i2c_request_info)); + __i2c_request.status = I2C_REQ_STATUS_FINISHED; + + // Enable interrupt + SH7305_INTC._->IPRH.I2C = 1; + SH7305_INTC.MSKCLR->IMR7 |= 0xf0; +} diff --git a/src/touch/i2c.h b/src/touch/i2c.h index a4d3e4a..8966ca8 100644 --- a/src/touch/i2c.h +++ b/src/touch/i2c.h @@ -8,9 +8,6 @@ // User API //--- -/* i2c_power_on() - power on the I2C peripheral and install handlers */ -extern void i2c_power_on(void); - /* i2c_reg_select() - select a register */ extern int i2c_reg_select(int reg); @@ -121,4 +118,26 @@ typedef struct { #define SH7305_I2C (*((volatile sh7305_i2c_t *)0xa4470000)) -#endif /* CLOVE_TOUCH_I2C_H */ +// state and world-switch + +#include + +/* i2c_configure() - driver/hardware configuration */ +extern void i2c_configure(void); + +/* i2c_hsave() - save hardware information */ +extern void i2c_hsave(touch_state_t *states); + +/* i2c_hrestore() - restore hardware information */ +extern void i2c_hrestore(touch_state_t *states); + +/* i2c_hpowered() - check if the module is powered */ +extern bool i2c_hpowered(void); + +/* i2c_hpoweron() - power on the module */ +extern void i2c_hpoweron(void); + +/* i2c_hpoweroff() - power off the module */ +extern void i2c_hpoweroff(void); + +#endif /* GINT_TOUCH_I2C_H */ diff --git a/src/touch/touch.c b/src/touch/touch.c index f0bce86..3b7d8b1 100644 --- a/src/touch/touch.c +++ b/src/touch/touch.c @@ -3,8 +3,13 @@ //---- #include +#include +#include #include +#include "./i2c.h" +#include "./adconv.h" + //--- // Internals //--- @@ -35,11 +40,27 @@ int touch_calib_set(touch_calib *calib) return 0; } +/* touch_get_dots() - get dots information */ +int touch_get_dots(struct _touch_addots *dots) +{ + struct _touch_adraw adraw; + struct _touch_adconv adconv; + int type; + + type = touchscreen_adconv_get_raw(&adraw); + type = touchscreen_adconv_get_conv(&adconv, &adraw, type); + type = touchscreen_adconv_get_dots(dots, &adconv, type); + return type; +} + // low-level API /* touch_next_event() - get the next touchscreen event */ key_event_t touch_next_event(void) { + key_event_t evt = { 0 }; + evt.type = KEYEV_NONE; + return evt; #if 0 struct _ts_adraw adraw; struct _ts_adconv adconv; @@ -51,3 +72,71 @@ key_event_t touch_next_event(void) return type; #endif } + +//--- +// Driver and state +//--- + +/* _touch_configure() - configure touch-screen */ +static void _touch_configure(void) +{ + volatile uint16_t *IO_PRCR = (void*)0xa405011c; + + i2c_configure(); + *(IO_PRCR) = (*(IO_PRCR) & 0xf3ff) | 0xc00; + __ts_calib.x_mul = 0x20b; + __ts_calib.x_div = 0x9b6; + __ts_calib.y_mul = 0x0f4; + __ts_calib.y_div = 0x66f; + __ts_calib.dual_debounce_frame = 0; + __ts_calib.dual_sensi_entry = 0x18; + __ts_calib.dual_sensi_leave = 0x24; +} + +/* _touch_hsave() - save hardware state */ +static void _touch_hsave(touch_state_t *state) +{ + volatile uint16_t *IO_PRCR = (void*)0xa405011c; + + i2c_hsave(state); + state->PRCR = *(IO_PRCR); +} + +/* _touch_hrestore() - restore hardware state */ +static void _touch_hrestore(touch_state_t *state) +{ + volatile uint16_t *IO_PRCR = (void*)0xa405011c; + + *(IO_PRCR) = state->PRCR; + i2c_hrestore(state); +} + +/* _touch_hpowered() - check if the module is powered */ +static bool _touch_hpowered(void) +{ + return i2c_hpowered(); +} + +/* _touch_hpoweron() - power on the module */ +static void _touch_hpoweron(void) +{ + i2c_hpoweron(); +} + +/* _touch_hpoweroff() - power off the module */ +static void _touch_hpoweroff(void) +{ + i2c_hpoweroff(); +} + +gint_driver_t drv_touch = { + .name = "TOUCH", + .configure = _touch_configure, + .hsave = (void *)_touch_hsave, + .hrestore = (void *)_touch_hrestore, + .hpowered = _touch_hpowered, + .hpoweron = _touch_hpoweron, + .hpoweroff = _touch_hpoweroff, + .state_size = sizeof(touch_state_t), +}; +GINT_DECLARE_DRIVER(16, drv_touch);