forked from 48productions/piuio-pico
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathinput_mux4067.c
164 lines (139 loc) · 4.98 KB
/
input_mux4067.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/**********************************************************/
/* SPDX-License-Identifier: MIT */
/* SPDX-FileCopyrightText: Copyright (c) 2023 sugoku */
/* https://github.com/sugoku/piuio-pico-brokeIO */
/**********************************************************/
#include "input_mux4067.h"
#include "bsp/board.h"
uint32_t mux4067_vals[MUX_COUNT] = {0};
uint32_t mux4067_vals_db[MUX_COUNT] = {0}; // debounced
// debouncing helper arrays
uint32_t mux4067_vals_last[MUX_COUNT] = {0};
uint32_t press_ts[MUX_COUNT][32] = {0};
uint32_t release_ts[MUX_COUNT][32] = {0};
#define MUX_P1_INPUTS_SIZE 5
const uint8_t mux_p1_inputs[] = {
MUX4067_P1_UPLEFT,
MUX4067_P1_UPRIGHT,
MUX4067_P1_CENTER,
MUX4067_P1_DOWNLEFT,
MUX4067_P1_DOWNRIGHT,
};
#define MUX_P2_INPUTS_SIZE 5
const uint8_t mux_p2_inputs[] = {
MUX4067_P2_UPLEFT,
MUX4067_P2_UPRIGHT,
MUX4067_P2_CENTER,
MUX4067_P2_DOWNLEFT,
MUX4067_P2_DOWNRIGHT,
};
void mux4067_init() {
// last_mux = 0;
gpio_init(MUX_ENABLE_PIN);
gpio_init(MUX1_IN_PIN);
gpio_init(MUX2_IN_PIN);
gpio_init(MUX_S0_PIN);
gpio_init(MUX_S1_PIN);
gpio_init(MUX_S2_PIN);
gpio_init(MUX_S3_PIN);
// set pinModes
gpio_set_dir(MUX_ENABLE_PIN, true); // set to output
gpio_set_dir(MUX1_IN_PIN, false); // set to input
gpio_set_dir(MUX2_IN_PIN, false); // set to input
#ifdef PULLUP_IN
gpio_pull_up(MUX1_IN_PIN); // enable pull-up resistor
gpio_pull_up(MUX2_IN_PIN); // enable pull-up resistor
#endif
gpio_set_dir(MUX_S0_PIN, true); // set to output
gpio_set_dir(MUX_S1_PIN, true); // set to output
gpio_set_dir(MUX_S2_PIN, true); // set to output
gpio_set_dir(MUX_S3_PIN, true); // set to output
// make sure everything is low
mux4067_reset();
// enable MUXes
mux4067_enable();
}
void mux4067_enable() {
gpio_put(MUX_ENABLE_PIN, 0);
}
void mux4067_disable() {
gpio_put(MUX_ENABLE_PIN, 1);
}
void mux4067_reset() {
// set read inputs to 0
for (int i = 0; i < 5; i++) {
mux4067_vals[i] = 0;
mux4067_vals_db[i] = 0;
}
// clear all selector pins
gpio_put(MUX_S0_PIN, 0);
gpio_put(MUX_S1_PIN, 0);
gpio_put(MUX_S2_PIN, 0);
gpio_put(MUX_S3_PIN, 0);
// disable MUX until enabled again
mux4067_disable();
}
void mux4067_update(uint8_t mux_p1, uint8_t mux_p2) {
for (int i = 15; i >= 0; i--) {
// set the selector pins to the current value
gpio_put(MUX_S3_PIN, (i >> 3) & 1);
gpio_put(MUX_S2_PIN, (i >> 2) & 1);
gpio_put(MUX_S1_PIN, (i >> 1) & 1);
gpio_put(MUX_S0_PIN, i & 1);
busy_wait_us(WAIT_INPUT_MUX4067); // wait for selector to change
// select mux based on if the input is related to P1 or P2 mux or neither
uint8_t mux1 = MUX_GLOBAL;
uint8_t mux2 = MUX_GLOBAL;
for (int j = 0; j < MUX_P1_INPUTS_SIZE; j++) {
if (i == mux_p1_inputs[j]) {
mux1 = mux_p1;
} else if (i + 16 == mux_p1_inputs[j]) {
mux2 = mux_p1;
}
}
for (int j = 0; j < MUX_P2_INPUTS_SIZE; j++) {
if (i == mux_p2_inputs[j]) {
mux1 = mux_p2;
} else if (i + 16 == mux_p2_inputs[j]) {
mux2 = mux_p2;
}
}
// read this value from BOTH muxes and store them in the ith bit and the (i+16)th bit respectively
#ifdef PULLUP_IN
SETORCLRBIT(mux4067_vals[mux1], i, !gpio_get(MUX1_IN_PIN));
SETORCLRBIT(mux4067_vals[mux2], i+16, !gpio_get(MUX2_IN_PIN));
#else
SETORCLRBIT(mux4067_vals[mux1], i, gpio_get(MUX1_IN_PIN));
SETORCLRBIT(mux4067_vals[mux2], i+16, gpio_get(MUX2_IN_PIN));
#endif
}
}
uint32_t mux4067_merged(uint32_t* vals) {
return vals[0] | vals[1] | vals[2] | vals[3] | vals[4];
}
void mux4067_debounce() {
#if defined(DEBOUNCING)
uint32_t current_ts = board_millis();
for (int mux = 0; mux < MUX_COUNT; mux++) {
for (int i = 0; i < 32; i++) {
uint32_t state = GETBIT(mux4067_vals[mux], i);
if (state != (GETBIT(mux4067_vals_last[mux], i))) {
// button state has changed
if (state) {
press_ts[mux][i] = current_ts;
} else {
release_ts[mux][i] = current_ts;
}
} else if (state && (current_ts - press_ts[mux][i]) >= DEBOUNCE_PRESS_TIME) {
// check if the button has been held for debounce time
SETBIT(mux4067_vals_db[mux], i); // set debounced button state
} else if (!state && (current_ts - release_ts[mux][i]) >= DEBOUNCE_RELEASE_TIME) {
CLRBIT(mux4067_vals_db[mux], i);
}
}
mux4067_vals_last[mux] = mux4067_vals[mux]; // store current button state for next iteration
}
#else
memcpy(mux4067_vals_db, mux4067_vals, MUX_COUNT);
#endif
}