Files
FizzyApple12_Waccon/WaccaTouchPanel/main.c
T

217 lines
6.7 KiB
C

#include <stdio.h>
#include <stdbool.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/irq.h"
#include "mpr121.h"
#define DEBUG_MODE // uncomment for debug messages (note: this will slow things down!)
#define MOTHERBOARD_I2C_PORT i2c1
#define MOTHERBOARD_I2C_HWID 0x10 // 0x1[1-6 depending on which position it's in bottom to top]
#define MOTHERBOARD_I2C_SDA 4
#define MOTHERBOARD_I2C_SCL 5
#define MOTHERBOARD_I2C_FREQ 100000
#define TOUCH_I2C_PORT i2c0
#define TOUCH_I2C_SDA 6
#define TOUCH_I2C_SCL 7
#define INNER_MPR121_ADDR 0x5A
#define OUTER_MPR121_ADDR 0x5B
#define TOUCH_I2C_FREQ 100000
#define MPR121_TOUCH_THRESHOLD 16
#define MPR121_RELEASE_THRESHOLD 10
typedef enum i2c_slave_event_t {
I2C_SLAVE_RECEIVE,
I2C_SLAVE_REQUEST,
I2C_SLAVE_FINISH,
} i2c_slave_event_t;
// Buttons
// [--] [--] [--] [--] [--]
// [--] [--] [--] [--] [--]
// [--] [--] [ ] [ ] [ ]
// [ ] [ ] [ ] [ ] [ ]
struct mpr121_sensor innerSensor;
uint16_t touchedInner = 0;
// Buttons
// [ ] [ ] [ ] [ ] [ ]
// [ ] [ ] [ ] [ ] [ ]
// [ ] [ ] [--] [--] [--]
// [--] [--] [--] [--] [--]
struct mpr121_sensor outerSensor;
uint16_t touchedOuter = 0;
// Button bits
// [ 0] [ 1] [ 2] [ 3] [ 4]
// [ 5] [ 6] [ 7] [ 8] [ 9]
// [10] [11] [12] [13] [14]
// [15] [16] [17] [18] [19]
uint32_t previousTouchDataPacket = 0;
bool writingPacket = false;
uint32_t touchDataPacket = 0;
bool transferInProgress;
static inline uint8_t i2c_read_byte(i2c_inst_t *i2c) {
i2c_hw_t *hw = i2c_get_hw(i2c);
assert(hw->status & I2C_IC_STATUS_RFNE_BITS);
return (uint8_t) hw->data_cmd;
}
static inline void i2c_write_byte(i2c_inst_t *i2c, uint8_t value) {
i2c_hw_t *hw = i2c_get_hw(i2c);
assert(hw->status & I2C_IC_STATUS_TFNF_BITS);
hw->data_cmd = value;
}
static void i2cSlaveHandler(i2c_inst_t *i2c, i2c_slave_event_t event) {
switch (event) {
case I2C_SLAVE_RECEIVE:
break;
case I2C_SLAVE_REQUEST: ;
uint32_t dataToSend = previousTouchDataPacket;
if (!writingPacket) dataToSend = touchDataPacket;
#ifdef DEBUG_MODE
printf("Master requested packet, sending [%u]...\n", dataToSend);
#endif
i2c_write_byte(MOTHERBOARD_I2C_PORT, (uint8_t) dataToSend);
i2c_write_byte(MOTHERBOARD_I2C_PORT, (uint8_t) dataToSend >> 8);
i2c_write_byte(MOTHERBOARD_I2C_PORT, (uint8_t) dataToSend >> 16);
i2c_write_byte(MOTHERBOARD_I2C_PORT, (uint8_t) dataToSend >> 24);
break;
case I2C_SLAVE_FINISH:
break;
default:
break;
}
}
static inline void finishTransfer() {
if (transferInProgress) {
i2cSlaveHandler(MOTHERBOARD_I2C_PORT, I2C_SLAVE_FINISH);
transferInProgress = false;
}
}
static void __not_in_flash_func(i2cSlaveI2CIRQHandler)() {
uint32_t intrStat = MOTHERBOARD_I2C_PORT->hw->intr_stat;
if (intrStat == 0) {
return;
}
if (intrStat & I2C_IC_INTR_STAT_R_TX_ABRT_BITS) {
MOTHERBOARD_I2C_PORT->hw->clr_tx_abrt;
finishTransfer();
}
if (intrStat & I2C_IC_INTR_STAT_R_START_DET_BITS) {
MOTHERBOARD_I2C_PORT->hw->clr_start_det;
finishTransfer();
}
if (intrStat & I2C_IC_INTR_STAT_R_STOP_DET_BITS) {
MOTHERBOARD_I2C_PORT->hw->clr_stop_det;
finishTransfer();
}
if (intrStat & I2C_IC_INTR_STAT_R_RX_FULL_BITS) {
transferInProgress = true;
i2cSlaveHandler(MOTHERBOARD_I2C_PORT, I2C_SLAVE_RECEIVE);
}
if (intrStat & I2C_IC_INTR_STAT_R_RD_REQ_BITS) {
MOTHERBOARD_I2C_PORT->hw->clr_rd_req;
transferInProgress = true;
i2cSlaveHandler(MOTHERBOARD_I2C_PORT, I2C_SLAVE_REQUEST);
}
}
void setupTouch() {
i2c_init(TOUCH_I2C_PORT, TOUCH_I2C_FREQ);
gpio_set_function(TOUCH_I2C_SDA, GPIO_FUNC_I2C);
gpio_set_function(TOUCH_I2C_SCL, GPIO_FUNC_I2C);
gpio_pull_up(TOUCH_I2C_SDA);
gpio_pull_up(TOUCH_I2C_SCL);
mpr121_init(TOUCH_I2C_PORT, INNER_MPR121_ADDR, &innerSensor);
mpr121_set_thresholds(MPR121_TOUCH_THRESHOLD, MPR121_RELEASE_THRESHOLD, &innerSensor);
mpr121_init(TOUCH_I2C_PORT, OUTER_MPR121_ADDR, &outerSensor);
mpr121_set_thresholds(MPR121_TOUCH_THRESHOLD, MPR121_RELEASE_THRESHOLD, &outerSensor);
}
void setupMotherboard() {
i2c_init(MOTHERBOARD_I2C_PORT, MOTHERBOARD_I2C_FREQ);
gpio_set_function(MOTHERBOARD_I2C_SDA, GPIO_FUNC_I2C);
gpio_set_function(MOTHERBOARD_I2C_SCL, GPIO_FUNC_I2C);
gpio_pull_up(MOTHERBOARD_I2C_SDA);
gpio_pull_up(MOTHERBOARD_I2C_SCL);
MOTHERBOARD_I2C_PORT->hw->enable = 0;
hw_set_bits(&MOTHERBOARD_I2C_PORT->hw->con, I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_BITS);
MOTHERBOARD_I2C_PORT->hw->enable = 1;
uint i2cHardwareIndex = i2c_hw_index(MOTHERBOARD_I2C_PORT);
i2c_set_slave_mode(MOTHERBOARD_I2C_PORT, false, MOTHERBOARD_I2C_HWID);
MOTHERBOARD_I2C_PORT->hw->intr_mask = I2C_IC_INTR_MASK_M_RX_FULL_BITS | I2C_IC_INTR_MASK_M_RD_REQ_BITS | I2C_IC_RAW_INTR_STAT_TX_ABRT_BITS | I2C_IC_INTR_MASK_M_STOP_DET_BITS | I2C_IC_INTR_MASK_M_START_DET_BITS;
uint IRQNumber = I2C0_IRQ + i2cHardwareIndex;
irq_set_exclusive_handler(IRQNumber, i2cSlaveI2CIRQHandler);
irq_set_enabled(IRQNumber, true);
}
#ifdef DEBUG_MODE
#define formatButton(data, number) (((data) & (1 << (number))) ? "#" : " ")
#define printMultiButtonRow(data1, data2, n1, n2, n3, n4, n5) printf("[%s] [%s] [%s] [%s] [%s]\n", formatButton(data1, n1), formatButton(data1, n2), formatButton(data2, n3), formatButton(data2, n4), formatButton(data2, n5))
#define printButtonRow(data, n1, n2, n3, n4, n5) printf("[%s] [%s] [%s] [%s] [%s]\n", formatButton(data, n1), formatButton(data, n2), formatButton(data, n3), formatButton(data, n4), formatButton(data, n5))
#endif
int main() {
stdio_init_all();
printf("Wacca Touch Panel v0.1\n");
setupTouch();
printf("Touch Ready\n");
setupMotherboard();
printf("Communications Ready\n");
while(1) {
mpr121_touched(&touchedInner, &innerSensor);
mpr121_touched(&touchedOuter, &outerSensor);
touchedInner = touchedInner & 0b0000111111111111;
touchedOuter = touchedOuter & 0b0000000011111111;
writingPacket = true;
touchDataPacket = ((uint32_t) touchedOuter << 12 | touchedInner) | 0x06900000;
#ifdef DEBUG_MODE
printf("-------------------\n");
printButtonRow(touchedInner, 0, 1, 2, 3, 4);
printButtonRow(touchedInner, 5, 6, 7, 8, 9);
printMultiButtonRow(touchedInner, touchedOuter, 10, 11, 0, 1, 2);
printButtonRow(touchedOuter, 3, 4, 5, 6, 7);
printf("-------------------\n");
#endif
writingPacket = false;
sleep_ms(10);
}
return 0;
}