2 * Copyright © 2017 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
16 #include <ao_flip_bits.h>
20 /* Decoded address driven by TPA/TPB signals */
23 /* Decoded data, driven by TPB signal */
32 /* Signals muxed between 1802 and STM */
35 return ao_gpio_get(MRD_PORT, MRD_BIT, MRD_PIN);
39 MRD_set(uint8_t value) {
40 ao_gpio_set(MRD_PORT, MRD_BIT, MRD_PIN, value);
45 return ao_gpio_get(MWR_PORT, MWR_BIT, MWR_PIN);
49 MWR_set(uint8_t value) {
50 ao_gpio_set(MWR_PORT, MWR_BIT, MWR_PIN, value);
56 ADDRESS = (ADDRESS & 0x00ff) | ((uint16_t) MA() << 8);
62 return ao_gpio_get(TPA_PORT, TPA_BIT, TPA_PIN);
66 TPA_set(uint8_t tpa) {
67 ao_gpio_set(TPA_PORT, TPA_BIT, TPA_PIN, tpa);
75 ADDRESS = (ADDRESS & 0xff00) | MA();
76 if (MWR() == 0 || MRD() == 0)
88 return ao_gpio_get(TPB_PORT, TPB_BIT, TPB_PIN);
92 TPB_set(uint8_t tpb) {
93 ao_gpio_set(TPB_PORT, TPB_BIT, TPB_PIN, tpb);
102 return (ao_gpio_get_all(MA_PORT) >> MA_SHIFT) & MA_MASK;
107 ao_gpio_set_mask(MA_PORT, ((uint16_t) ma) << MA_SHIFT, MA_MASK << MA_SHIFT);
110 /* Tri-state data bus */
114 return ao_flip_bits_8[(ao_gpio_get_all(BUS_PORT) >> BUS_SHIFT) & BUS_MASK];
118 BUS_set(uint8_t bus) {
119 ao_gpio_set_mask(BUS_PORT, ao_flip_bits_8[bus] << BUS_SHIFT, BUS_MASK << BUS_SHIFT);
125 ao_set_output_mask(BUS_PORT, BUS_MASK << BUS_SHIFT);
131 ao_set_input_mask(BUS_PORT, BUS_MASK << BUS_SHIFT);
134 /* Pins controlled by 1802 */
137 return ao_flip_bits_2[(ao_gpio_get_all(SC_PORT) >> SC_SHIFT) & SC_MASK];
142 return ao_gpio_get(Q_PORT, Q_BIT, Q_PIN);
147 return (ao_gpio_get_all(N_PORT) >> N_SHIFT) & N_MASK;
150 /* Pins controlled by STM */
153 return (ao_gpio_get_all(EF_PORT) >> EF_SHIFT) & EF_MASK;
158 ao_gpio_set_mask(EF_PORT, ef << EF_SHIFT, EF_MASK << EF_SHIFT);
163 return ao_gpio_get(DMA_IN_PORT, DMA_IN_BIT, DMA_IN_PIN);
167 DMA_IN_set(uint8_t dma_in) {
168 ao_gpio_set(DMA_IN_PORT, DMA_IN_BIT, DMA_IN_PIN, dma_in);
173 return ao_gpio_get(DMA_OUT_PORT, DMA_OUT_BIT, DMA_OUT_PIN);
177 DMA_OUT_set(uint8_t dma_out) {
178 ao_gpio_set(DMA_OUT_PORT, DMA_OUT_BIT, DMA_OUT_PIN, dma_out);
183 return ao_gpio_get(INT_PORT, INT_BIT, INT_PIN);
187 INT_set(uint8_t dma_out) {
188 ao_gpio_set(INT_PORT, INT_BIT, INT_PIN, dma_out);
193 return ao_gpio_get(CLEAR_PORT, CLEAR_BIT, CLEAR_PIN);
197 CLEAR_set(uint8_t dma_out) {
198 ao_gpio_set(CLEAR_PORT, CLEAR_BIT, CLEAR_PIN, dma_out);
203 return ao_gpio_get(WAIT_PORT, WAIT_BIT, WAIT_PIN);
207 WAIT_set(uint8_t dma_out) {
208 ao_gpio_set(WAIT_PORT, WAIT_BIT, WAIT_PIN, dma_out);
213 /* Latch low address and data on rising edge of TPB */
222 /* Latch high address on rising edge of TPA */
227 #define ao_1802_in(port, bit, mode) do { \
228 ao_gpio_set_mode(port, bit, mode); \
229 ao_set_input(port, bit); \
232 #define ao_1802_in_isr(port, bit, mode) do { \
233 ao_gpio_set_mode(port, bit, mode); \
234 ao_set_input(port, bit); \
235 ao_exti_enable(port, bit); \
238 #define ao_1802_out_isr(port, bit) do { \
239 ao_exti_disable(port, bit); \
240 ao_set_output(port, bit); \
246 if (MUX_CONTROL != _MUX_1802) {
247 /* Set pins to input, but pulled to idle value */
248 ao_1802_in(MRD_PORT, MRD_BIT, AO_EXTI_MODE_PULL_UP);
249 ao_1802_in(MWR_PORT, MWR_BIT, AO_EXTI_MODE_PULL_UP);
250 ao_1802_in_isr(TPB_PORT, TPB_BIT, AO_EXTI_MODE_PULL_DOWN);
251 ao_1802_in_isr(TPA_PORT, TPA_BIT, AO_EXTI_MODE_PULL_DOWN);
252 ao_set_input_mask(MA_PORT, MA_MASK << MA_SHIFT);
254 ao_gpio_set(MUX_PORT, MUX_BIT, MUX_PIN, 0);
256 /* Now change the pins to eliminate the pull up/down */
257 ao_gpio_set_mode(MRD_PORT, MRD_BIT, 0);
258 ao_gpio_set_mode(MWR_PORT, MWR_BIT, 0);
259 ao_gpio_set_mode(TPB_PORT, TPB_BIT, 0);
260 ao_gpio_set_mode(TPA_PORT, TPA_BIT, 0);
262 MUX_CONTROL = _MUX_1802;
269 if (MUX_CONTROL != _MUX_STM) {
270 /* Set the pins back to pull to the idle value */
271 ao_gpio_set_mode(MRD_PORT, MRD_BIT, AO_EXTI_MODE_PULL_UP);
272 ao_gpio_set_mode(MWR_PORT, MWR_BIT, AO_EXTI_MODE_PULL_UP);
273 ao_gpio_set_mode(TPB_PORT, TPB_BIT, AO_EXTI_MODE_PULL_DOWN);
274 ao_gpio_set_mode(TPA_PORT, TPA_BIT, AO_EXTI_MODE_PULL_DOWN);
276 ao_gpio_set(MUX_PORT, MUX_BIT, MUX_PIN, 1);
278 /* Now set the pins as output, driven to the idle value */
279 ao_set_output(MRD_PORT, MRD_BIT, MRD_PIN, 1);
280 ao_set_output(MWR_PORT, MWR_BIT, MWR_PIN, 1);
281 ao_set_output(TPB_PORT, TPB_BIT, TPB_PIN, 0);
282 ao_set_output(TPA_PORT, TPA_BIT, TPA_PIN, 0);
283 ao_set_output_mask(MA_PORT, MA_MASK << MA_SHIFT);
284 MUX_CONTROL = _MUX_STM;
291 /* Multiplexed signals*/
293 /* active low signals */
294 ao_enable_input(MRD_PORT, MRD_BIT, AO_EXTI_MODE_PULL_UP);
295 ao_enable_input(MWR_PORT, MWR_BIT, AO_EXTI_MODE_PULL_UP);
297 /* active high signals with interrupts */
298 ao_exti_setup(TPA_PORT, TPA_BIT,
299 AO_EXTI_MODE_PULL_DOWN | AO_EXTI_MODE_RISING | AO_EXTI_MODE_FALLING,
301 ao_exti_setup(TPB_PORT, TPB_BIT,
302 AO_EXTI_MODE_PULL_DOWN | AO_EXTI_MODE_RISING | AO_EXTI_MODE_FALLING,
305 /* multiplexed address bus */
306 ao_enable_input_mask(MA_PORT, MA_MASK << MA_SHIFT, 0);
310 ao_enable_input_mask(BUS_PORT, BUS_MASK << BUS_SHIFT, 0);
312 /* Pins controlled by 1802 */
313 ao_enable_input_mask(SC_PORT, SC_MASK << SC_SHIFT, 0);
314 ao_enable_input(Q_PORT, Q_BIT, 0);
315 ao_enable_input_mask(N_PORT, N_MASK << N_SHIFT, 0);
317 /* Pins controlled by STM */
318 ao_enable_output_mask(EF_PORT, 0, EF_MASK << EF_SHIFT);
319 ao_enable_output(DMA_IN_PORT, DMA_IN_BIT, DMA_IN_PIN, 1);
320 ao_enable_output(DMA_OUT_PORT, DMA_OUT_BIT, DMA_OUT_PIN, 1);
321 ao_enable_output(INT_PORT, INT_BIT, INT_PIN, 1);
322 ao_enable_output(CLEAR_PORT, CLEAR_BIT, CLEAR_PIN, 1);
323 ao_enable_output(WAIT_PORT, WAIT_BIT, WAIT_PIN, 1);
325 /* Force configuration to STM so that MUX_1802 will do something */
326 MUX_CONTROL = _MUX_STM;