]>
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
);
153 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
158 /* Invalid pin mode */
165 void gpio_write(int pin
, uint8_t val
)
167 port_t
*p
= pinlist
[pin
].adr
;
168 uint8_t bit
= pinlist
[pin
].mask
;
170 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
178 int gpio_read(int pin
)
180 port_t
*p
= pinlist
[pin
].adr
;
181 uint8_t bit
= pinlist
[pin
].mask
;
183 return (p
->pin
& bit
) != 0;
186 gpiomode_t
gpio_config_get(int pin
)
188 uint8_t timertype
= pinlist
[pin
].timer
;
190 if (timertype
& TIMER
) {
193 if (timertype
& CHANA
)
198 switch (timertype
& TIMER
) {
200 if (TCCR0A
& chan_mask
)
204 if (TCCR1A
& chan_mask
)
208 if (TCCR2A
& chan_mask
)
214 port_t
*p
= pinlist
[pin
].adr
;
215 uint8_t bit
= pinlist
[pin
].mask
;
227 * return -1: pin has no timer output
228 * 0: pin is not configured for timer output
232 long gpio_clockdiv_get(int pin
)
236 const FLASH
uint8_t *pstab
;
238 uint8_t timertype
= pinlist
[pin
].timer
;
239 if ((timertype
& TIMER
) == 0)
242 if (gpio_config_get(pin
) != OUTPUT_TIMER
)
245 switch (timertype
& TIMER
) {
262 prescale
= (prescale
& 0x07) - 1;
265 pstab
= (timertype
& TIMER
) == TIMER2
?
266 prescale_factors_2
: prescale_factors_01
;
269 divider
*= pstab
[prescale
];
271 if ((timertype
& (CHANA
|T_16BIT
)) == CHANA
)
277 int gpio_clockdiv_set(int pin
, unsigned long divider
)
282 const FLASH
uint8_t *pstab
;
284 uint8_t timertype
= pinlist
[pin
].timer
;
285 if ((timertype
& TIMER
) == 0)
292 if ((timertype
& (CHANA
|T_16BIT
)) == CHANA
)
295 if (ltop
> 1024 * ((timertype
& T_16BIT
) ? (1L<<16) : (1L<<8)))
299 pstab
= (timertype
& TIMER
) == TIMER2
?
300 prescale_factors_2
: prescale_factors_01
;
302 // debug("** clockdiv_set: pin: %d, ltop: %lu, prescale: %d\n",
303 // pin, ltop, prescale);
305 while (ltop
> ((timertype
& T_16BIT
) ? (1L<<16) : (1L<<8))) {
306 // debug("** clockdiv_set: pin: %d, ltop: %lu, prescale: %d, *pstab %d\n",
307 // pin, ltop, prescale, *pstab);
320 // PING |= _BV(0); /* Debug */
322 switch (timertype
& TIMER
) {
324 PRR0
&= ~_BV(PRTIM0
);
325 TCCR0B
= (1 << WGM02
);
328 if (timertype
& CHANA
) {
329 TCCR0A
= (PWMTOGGLE
<< COM0A0
) | (0b11 << WGM00
);
332 TCCR0A
= (PWMPOS
<< COM0B0
) | (0b11 << WGM10
);
334 TCCR0B
= (1 << WGM02
) | (prescale
<< CS10
);
338 PRR0
&= ~_BV(PRTIM1
);
339 TCCR1B
= (0b11 << WGM12
);
342 if (timertype
& CHANA
) {
344 TCCR1A
= (PWMPOS
<< COM1A0
) | (0b10 << WGM10
);
347 TCCR1A
= (PWMPOS
<< COM1B0
) | (0b10 << WGM10
);
349 // debug("pin: %d, top: %u,"
350 // " ICR1: %u, OCR1A: %u, OCR1B: %u\n",
351 // pin, top, ICR1, OCR1A, OCR1B);
353 TCCR1B
= (0b11 << WGM12
) | (prescale
<< CS10
);
357 PRR0
&= ~_BV(PRTIM2
);
358 TCCR2B
= (1 << WGM22
);
361 if (timertype
& CHANA
) {
362 TCCR2A
= (PWMTOGGLE
<< COM2A0
) | (0b11 << WGM20
);
365 TCCR2A
= (PWMPOS
<< COM2B0
) | (0b11 << WGM10
);
367 TCCR2B
= (1 << WGM22
) | (prescale
<< CS10
);
371 // PING |= _BV(0); /* Debug */
373 gpio_config(pin
, OUTPUT_TIMER
);