]>
cloudbase.mooo.com Git - z180-stamp.git/blob - avr/gpio.c
2 * (C) Copyright 2014 Leo C. <erbl259-lmu@yahoo.de>
4 * SPDX-License-Identifier: GPL-2.0+
8 #include <util/atomic.h>
15 Pin Name Port Timer Mode max div max div min f [Hz]
16 --------------------------------------------------------------------------------
17 0 PG5 OC0B PWM (2**8)*1024 262144 70.31
19 2 CLK2 PB4 OC2A Toggle (2**8)*1024*2 524288 35.16
20 3 ZCLK PB5 OC1A PWM (2**16)*1024 67108864 0.2746
21 4 PB6 OC1B PWM (2**16)*1024 67108864 0.2746
22 5 PB7 OC0A Toggle (2**8)*1024*2 524288 35.16
28 --------------------------------------------------------------------------------
31 pre Timer0 Timer1 Timer2
32 --------------------------------------------------
38 5 1024 x4 1024 x4 128 x2
41 --------------------------------------------------
44 #define PWMTOGGLE 0b01
49 const FLASH
uint8_t prescale_factors_01
[] =
52 const FLASH
uint8_t prescale_factors_2
[] =
53 { 8, 4, 2, 2, 2, 4, 0 };
55 typedef volatile struct {
65 #define TIMER0 (1 << 0)
66 #define TIMER1 (2 << 0)
67 #define TIMER2 (3 << 0)
68 #define TIMER (3 << 0)
69 #define T_16BIT (1 << 3)
70 #define CHANA (1 << 4)
71 #define CHANB (0 << 4)
76 const FLASH
struct pindef_s pinlist
[GPIO_MAX
] = {
77 { (port_t
*) &PING
, _BV(5), TIMER0
| CHANB
},
78 { (port_t
*) &PING
, _BV(4), NO_TIMER
},
79 { (port_t
*) &PINB
, _BV(4), TIMER2
| CHANA
},
80 { (port_t
*) &PINB
, _BV(5), TIMER1
| CHANA
| T_16BIT
},
81 { (port_t
*) &PINB
, _BV(6), TIMER1
| CHANB
| T_16BIT
},
82 { (port_t
*) &PINB
, _BV(7), TIMER0
| CHANA
},
83 { (port_t
*) &PING
, _BV(3), NO_TIMER
},
84 { (port_t
*) &PING
, _BV(2), NO_TIMER
},
85 { (port_t
*) &PING
, _BV(1), NO_TIMER
},
86 { (port_t
*) &PING
, _BV(0), NO_TIMER
},
87 { (port_t
*) &PINE
, _BV(7), NO_TIMER
},
90 void gpio_timer_off(uint8_t timertype
)
94 if (timertype
& CHANA
)
99 switch (timertype
& TIMER
) {
101 if (TCCR0A
& chan_mask
) {
108 if (TCCR1A
& chan_mask
) {
115 if (TCCR2A
& chan_mask
) {
124 int gpio_config(int pin
, gpiomode_t mode
)
126 if ((unsigned) pin
>= ARRAY_SIZE(pinlist
)) {
127 /* Invalid pin number */
131 port_t
*p
= pinlist
[pin
].adr
;
132 uint8_t bit
= pinlist
[pin
].mask
;
136 gpio_timer_off(pinlist
[pin
].timer
);
137 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
143 gpio_timer_off(pinlist
[pin
].timer
);
144 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
150 gpio_timer_off(pinlist
[pin
].timer
);
152 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
157 /* Invalid pin mode */
164 void gpio_write(int pin
, uint8_t val
)
166 port_t
*p
= pinlist
[pin
].adr
;
167 uint8_t bit
= pinlist
[pin
].mask
;
169 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
177 int gpio_read(int pin
)
179 port_t
*p
= pinlist
[pin
].adr
;
180 uint8_t bit
= pinlist
[pin
].mask
;
182 return (p
->pin
& bit
) != 0;
185 gpiomode_t
gpio_config_get(int pin
)
187 uint8_t timertype
= pinlist
[pin
].timer
;
189 if (timertype
& TIMER
) {
192 if (timertype
& CHANA
)
197 switch (timertype
& TIMER
) {
199 if (TCCR0A
& chan_mask
)
203 if (TCCR1A
& chan_mask
)
207 if (TCCR2A
& chan_mask
)
213 port_t
*p
= pinlist
[pin
].adr
;
214 uint8_t bit
= pinlist
[pin
].mask
;
226 * return -1: pin has no timer output
227 * 0: pin is not configured for timer output
231 long gpio_clockdiv_get(int pin
)
235 const FLASH
uint8_t *pstab
;
237 uint8_t timertype
= pinlist
[pin
].timer
;
238 if ((timertype
& TIMER
) == 0)
241 if (gpio_config_get(pin
) != OUTPUT_TIMER
)
244 switch (timertype
& TIMER
) {
261 prescale
= (prescale
& 0x07) - 1;
264 pstab
= (timertype
& TIMER
) == TIMER2
?
265 prescale_factors_2
: prescale_factors_01
;
268 divider
*= pstab
[prescale
];
270 if ((timertype
& (CHANA
|T_16BIT
)) == CHANA
)
276 int gpio_clockdiv_set(int pin
, unsigned long divider
)
281 const FLASH
uint8_t *pstab
;
283 uint8_t timertype
= pinlist
[pin
].timer
;
284 if ((timertype
& TIMER
) == 0)
291 if ((timertype
& (CHANA
|T_16BIT
)) == CHANA
)
294 if (ltop
> 1024 * ((timertype
& T_16BIT
) ? (1L<<16) : (1L<<8)))
298 pstab
= (timertype
& TIMER
) == TIMER2
?
299 prescale_factors_2
: prescale_factors_01
;
301 // debug("** clockdiv_set: pin: %d, ltop: %lu, prescale: %d\n",
302 // pin, ltop, prescale);
304 while (ltop
> ((timertype
& T_16BIT
) ? (1L<<16) : (1L<<8))) {
305 // debug("** clockdiv_set: pin: %d, ltop: %lu, prescale: %d, *pstab %d\n",
306 // pin, ltop, prescale, *pstab);
319 // PING |= _BV(0); /* Debug */
321 switch (timertype
& TIMER
) {
323 PRR0
&= ~_BV(PRTIM0
);
324 TCCR0B
= (1 << WGM02
);
327 if (timertype
& CHANA
) {
328 TCCR0A
= (PWMTOGGLE
<< COM0A0
) | (0b11 << WGM00
);
331 TCCR0A
= (PWMPOS
<< COM0B0
) | (0b11 << WGM10
);
333 TCCR0B
= (1 << WGM02
) | (prescale
<< CS10
);
337 PRR0
&= ~_BV(PRTIM1
);
338 TCCR1B
= (0b11 << WGM12
);
341 if (timertype
& CHANA
) {
343 TCCR1A
= (PWMPOS
<< COM1A0
) | (0b10 << WGM10
);
346 TCCR1A
= (PWMPOS
<< COM1B0
) | (0b10 << WGM10
);
348 // debug("pin: %d, top: %u,"
349 // " ICR1: %u, OCR1A: %u, OCR1B: %u\n",
350 // pin, top, ICR1, OCR1A, OCR1B);
352 TCCR1B
= (0b11 << WGM12
) | (prescale
<< CS10
);
356 PRR0
&= ~_BV(PRTIM2
);
357 TCCR2B
= (1 << WGM22
);
360 if (timertype
& CHANA
) {
361 TCCR2A
= (PWMTOGGLE
<< COM2A0
) | (0b11 << WGM20
);
364 TCCR2A
= (PWMPOS
<< COM2B0
) | (0b11 << WGM10
);
366 TCCR2B
= (1 << WGM22
) | (prescale
<< CS10
);
370 // PING |= _BV(0); /* Debug */
372 gpio_config(pin
, OUTPUT_TIMER
);