summaryrefslogtreecommitdiffstats
path: root/keyboards/handwired/symmetric70_proto/matrix_fast/matrix_config_expand.c
blob: 0df605db47c5e10cc0747d4f1e632781d96c4bce (plain)
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/*
Copyright 2021 mtei

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
// clang-format off

#include "matrix_extr.h"

#ifdef DEBUG_MATRIX_CONFIG
// config expand debug
//   avr-gcc -DDEBUG_MATRIX_CONFIG=\"test_config.h\" -E -C matrix_config_expand.c
#    include DEBUG_MATRIX_CONFIG
#endif

#undef NO_PIN /* cancel NO_PIN define in tmk_core/common/pin_defs.h */
#define NO_PIN  NO_PORT, 0
#if MATRIX_TYPE == DIRECT_SWITCH
#    undef MATRIX_OUT_PORTS
#    define MATRIX_OUT_PINS  (0, NO_PIN)
#endif

#include "cpp_map.h"

#if defined(MATRIX_EXTENSION_74HC157) || defined(MATRIX_EXTENSION_74HC153)
#   define  MATRIX_EXTENSION "matrix_extension_74hc15x.c"
#endif

#ifdef MATRIX_EXTENSION
#    include MATRIX_EXTENSION
#endif

#ifdef MATRIX_GPIO_NEED_SEPARATE_ATOMIC
#    ifndef setMatrixInputHigh
#        define setMatrixInputHigh(dev, port, bit) do { if ((dev) == MCU_GPIO) { setPortBitInputHigh_atomic(port, bit); }} while(0)
#    endif
#    ifndef setMatrixOutput_writeHighZ
#        define setMatrixOutput_writeHighZ(dev, port, bit) do { if ((dev) == MCU_GPIO) { setPortBitInputHigh_atomic(port, bit); }} while(0)
#    endif
#    ifndef setMatrixOutput_writeLow
#        define setMatrixOutput_writeLow(dev, port, bit) do { if ((dev) == MCU_GPIO) { setPortBitOutput_writeLow_atomic(port, bit); }} while(0)
#    endif
#else
#    ifndef setMatrixInputHigh
#        define setMatrixInputHigh(dev, port, bit) do { if ((dev) == MCU_GPIO) { setPortBitInputHigh(port, bit); }} while(0)
#    endif
#    ifndef setMatrixOutput_writeHighZ
#        define setMatrixOutput_writeHighZ(dev, port, bit) do { if ((dev) == MCU_GPIO) { setPortBitInputHigh(port, bit); }} while(0)
#    endif
#    ifndef setMatrixOutput_writeLow
#        define setMatrixOutput_writeLow(dev, port, bit) do { if ((dev) == MCU_GPIO) { setPortBitOutput_writeLow(port, bit); }} while(0)
#    endif
#endif

#ifndef readMatrixPort
#    define readMatrixPort(dev, port) (((dev) == MCU_GPIO) ? readPort(port) : 0)
#endif
#ifndef getMatrixInputMaskBit
#    define getMatrixInputMaskBit(dev, bit) (((dev) != NO_DEVICE) ? _BV((bit)&0xF) : 0)
#endif

#ifndef init_extension
#    define init_extension()
#endif

enum DEVICE_NAME {
    MCU_GPIO,
    NO_DEVICE,
#ifdef MATRIX_DEVICES
    MATRIX_DEVICES
#endif
};

#define _INPUT_PORTS_ENUM_ELEMENT(name, dev, port) inport_index_##name,
#define INPUT_PORTS_ENUM_ELEMENT(x) _INPUT_PORTS_ENUM_ELEMENT x
enum INPUT_PORTS {
    INPUT_PORTS_ENUM_ELEMENT((NO_PORT, NO_DEVICE, 0))
    MAP(INPUT_PORTS_ENUM_ELEMENT, MATRIX_IN_PORTS)
    NUM_OF_INPUT_PORTS
};

#define _INPUT_PINS_ENUM_ELEMENT(index, port, bit) inpin_index_##index,
#define INPUT_PINS_ENUM_ELEMENT(x) _INPUT_PINS_ENUM_ELEMENT x
enum INPUT_PINS {
    MAP(INPUT_PINS_ENUM_ELEMENT, MATRIX_IN_PINS)
    END_inpin_index
};

#define _OUTPUT_PORTS_ENUM_ELEMENT(name, dev, port) outport_index_##name,
#define OUTPUT_PORTS_ENUM_ELEMENT(x) _OUTPUT_PORTS_ENUM_ELEMENT x
enum OUTPUT_PORTS {
    OUTPUT_PORTS_ENUM_ELEMENT((NO_PORT, NO_DEVICE, 0))
#ifdef MATRIX_OUT_PORTS
    MAP(OUTPUT_PORTS_ENUM_ELEMENT, MATRIX_OUT_PORTS)
#endif
    NUM_OF_OUTPUT_PORTS
};

#define _OUTPUT_PINS_ENUM_ELEMENT(index, port, bit) outpin_index_##index,
#define OUTPUT_PINS_ENUM_ELEMENT(x) _OUTPUT_PINS_ENUM_ELEMENT x
enum OUTPUT_PINS {
    MAP(OUTPUT_PINS_ENUM_ELEMENT, MATRIX_OUT_PINS)
    END_outpin_index
};

port_width_t iport_mask[NUM_OF_INPUT_PORTS];

#define _INPUT_PORTS_LIST_ELEMENT(name, dev, port) \
    [inport_index_##name] = { dev, port },
#define INPUT_PORTS_LIST_ELEMENT(x) _INPUT_PORTS_LIST_ELEMENT x
LOCAL_DATA
const port_descriptor inport_list[NUM_OF_INPUT_PORTS] = {
    INPUT_PORTS_LIST_ELEMENT((NO_PORT, NO_DEVICE, 0))
    MAP(INPUT_PORTS_LIST_ELEMENT, MATRIX_IN_PORTS)
};

#define _OUTPUT_PORTS_LIST_ELEMENT(name, dev, port) \
    [outport_index_##name] = { dev, port },
#define OUTPUT_PORTS_LIST_ELEMENT(x) _OUTPUT_PORTS_LIST_ELEMENT x
LOCAL_DATA
const port_descriptor outport_list[NUM_OF_OUTPUT_PORTS] = {
    OUTPUT_PORTS_LIST_ELEMENT((NO_PORT, NO_DEVICE, 0))
#ifdef MATRIX_OUT_PORTS
    MAP(OUTPUT_PORTS_LIST_ELEMENT, MATRIX_OUT_PORTS)
#endif
};

#define _SELECT_OUTPUT_PIN(index, pname, bit) \
    case outpin_index_##index: \
        setMatrixOutput_writeLow(outport_list[outport_index_##pname].device,     \
                                 outport_list[outport_index_##pname].port, bit); \
    break;
#define SELECT_OUTPUT_PIN(x) _SELECT_OUTPUT_PIN x
LOCAL_FUNC ALWAYS_INLINE void select_output(uint8_t out_index);
LOCAL_FUNC
void select_output(uint8_t out_index) {
    switch (out_index) {
        MAP(SELECT_OUTPUT_PIN, MATRIX_OUT_PINS)
    }
}

#define _UNSELECT_OUTPUT_PIN(index, pname, bit) \
    case outpin_index_##index: \
        setMatrixOutput_writeHighZ(outport_list[outport_index_##pname].device,     \
                                   outport_list[outport_index_##pname].port, bit); \
    break;
#define UNSELECT_OUTPUT_PIN(x) _UNSELECT_OUTPUT_PIN x
LOCAL_FUNC ALWAYS_INLINE void unselect_output_inline(uint8_t out_index);
LOCAL_FUNC
void unselect_output_inline(uint8_t out_index) {
    switch (out_index) {
        MAP(UNSELECT_OUTPUT_PIN, MATRIX_OUT_PINS)
    }
}

#define _INIT_INPUT_PIN(index, pname, bit) \
    setMatrixInputHigh(inport_list[inport_index_##pname].device,    \
                       inport_list[inport_index_##pname].port, bit);
#define INIT_INPUT_PIN(x) _INIT_INPUT_PIN x
LOCAL_FUNC
void init_input_ports(void) {
    MAP(INIT_INPUT_PIN, MATRIX_IN_PINS)
}

#define _INIT_INPORT_MASK(index, pname, bit) \
    iport_mask[inport_index_##pname] |= getMatrixInputMaskBit(inport_list[inport_index_##pname].device, bit);
#define INIT_INPORT_MASK(x)  _INIT_INPORT_MASK x
LOCAL_FUNC
void init_inport_mask(void) {
    for (int i = 0; i < NUM_OF_INPUT_PORTS; i++ ) {
        iport_mask[i] = 0;
    }
    MAP(INIT_INPORT_MASK, MATRIX_IN_PINS)
}

#define _READ_INPUT_PORT(name, dev, port) \
    buffer[inport_index_##name] = readMatrixPort(dev, port);
#define READ_INPUT_PORT(x) _READ_INPUT_PORT x
LOCAL_FUNC
ALWAYS_INLINE void read_all_input_ports(port_width_t buffer[NUM_OF_INPUT_PORTS], bool wait_unselect);
LOCAL_FUNC
void read_all_input_ports(port_width_t buffer[NUM_OF_INPUT_PORTS], bool wait_unselect) {
    READ_INPUT_PORT((NO_PORT, NO_DEVICE, 0))
    MAP(READ_INPUT_PORT, MATRIX_IN_PORTS)
}

#define _MASK_INPUT(name, dev, port) \
    mask |= ((~buffer[inport_index_##name]) & iport_mask[inport_index_##name]);
#define MASK_INPUT(x) _MASK_INPUT x
LOCAL_FUNC ALWAYS_INLINE void wait_unselect_done(void);
LOCAL_FUNC
void wait_unselect_done(void) {
    port_width_t mask;
    port_width_t buffer[NUM_OF_INPUT_PORTS];
    do {
        read_all_input_ports(buffer, true);
        MATRIX_DEBUG_DELAY_END();
        mask = 0;
        MAP(MASK_INPUT, MATRIX_IN_PORTS);
        MATRIX_DEBUG_DELAY_START();
    } while (mask != 0);
}

#define _BUILD_INPUT_PORT(index, pname, bit) \
    result |= (buffer[inport_index_##pname] & _BV(bit)) ? 0 : _BV(inpin_index_##index);
#define BUILD_INPUT_PORT(x) _BUILD_INPUT_PORT x
LOCAL_FUNC ALWAYS_INLINE matrix_line_t build_matrix_line(port_width_t buffer[NUM_OF_INPUT_PORTS]);
LOCAL_FUNC
matrix_line_t build_matrix_line(port_width_t buffer[NUM_OF_INPUT_PORTS]) {
    matrix_line_t result = 0;
    MAP(BUILD_INPUT_PORT, MATRIX_IN_PINS);
    return result;
}

#define _BUILD_INPUT_PORT_DIRECT(index, pname, bit) \
    matrix[(inpin_index_##index)/MATRIX_COLS] \
        |= (buffer[inport_index_##pname] & _BV(bit)) ? 0 : _BV((inpin_index_##index)%MATRIX_COLS);
#define BUILD_INPUT_PORT_DIRECT(x) _BUILD_INPUT_PORT_DIRECT x
LOCAL_FUNC ALWAYS_INLINE void build_matrix_direct(port_width_t buffer[NUM_OF_INPUT_PORTS], matrix_line_t matrix[]);
LOCAL_FUNC
void build_matrix_direct(port_width_t buffer[NUM_OF_INPUT_PORTS], matrix_line_t matrix[]) {
    MAP(BUILD_INPUT_PORT_DIRECT, MATRIX_IN_PINS);
}