]>
cloudbase.mooo.com Git - z180-stamp.git/blob - avr/gpio.c
2 #include <util/atomic.h>
10 Pin Name Port Timer Mode max div max div min f [Hz]
11 --------------------------------------------------------------------------------
12 0 PG5 OC0B PWM (2**8)*1024 262144 70.31
14 2 CLK2 PB4 OC2A Toggle (2**8)*1024*2 524288 35.16
15 3 ZCLK PB5 OC1A PWM (2**16)*1024 67108864 0.2746
16 4 PB6 OC1B PWM (2**16)*1024 67108864 0.2746
17 5 PB7 OC0A Toggle (2**8)*1024*2 524288 35.16
23 --------------------------------------------------------------------------------
26 pre Timer0 Timer1 Timer2
27 --------------------------------------------------
33 5 1024 x4 1024 x4 128 x2
36 --------------------------------------------------
39 #define PWMTOGGLE 0b01
44 const FLASH
uint8_t prescale_factors_01
[] =
47 const FLASH
uint8_t prescale_factors_2
[] =
48 { 8, 4, 2, 2, 2, 4, 0 };
50 typedef volatile struct {
60 #define TIMER0 (1 << 0)
61 #define TIMER1 (2 << 0)
62 #define TIMER2 (3 << 0)
63 #define TIMER (3 << 0)
64 #define T_16BIT (1 << 3)
65 #define CHANA (1 << 4)
66 #define CHANB (0 << 4)
71 const FLASH
struct pindef_s pinlist
[GPIO_MAX
] = {
72 { (port_t
*) &PING
, _BV(5), TIMER0
| CHANB
},
73 { (port_t
*) &PING
, _BV(4), NO_TIMER
},
74 { (port_t
*) &PINB
, _BV(4), TIMER2
| CHANA
},
75 { (port_t
*) &PINB
, _BV(5), TIMER1
| CHANA
| T_16BIT
},
76 { (port_t
*) &PINB
, _BV(6), TIMER1
| CHANB
| T_16BIT
},
77 { (port_t
*) &PINB
, _BV(7), TIMER0
| CHANA
},
78 { (port_t
*) &PING
, _BV(3), NO_TIMER
},
79 { (port_t
*) &PING
, _BV(2), NO_TIMER
},
80 { (port_t
*) &PING
, _BV(1), NO_TIMER
},
81 { (port_t
*) &PING
, _BV(0), NO_TIMER
},
82 { (port_t
*) &PINE
, _BV(7), NO_TIMER
},
85 void gpio_timer_off(uint8_t timertype
)
89 if (timertype
& CHANA
)
94 switch (timertype
& TIMER
) {
96 if (TCCR0A
& chan_mask
) {
103 if (TCCR1A
& chan_mask
) {
110 if (TCCR2A
& chan_mask
) {
119 int gpio_config(int pin
, gpiomode_t mode
)
121 if ((unsigned) pin
>= ARRAY_SIZE(pinlist
)) {
122 /* Invalid pin number */
126 port_t
*p
= pinlist
[pin
].adr
;
127 uint8_t bit
= pinlist
[pin
].mask
;
131 gpio_timer_off(pinlist
[pin
].timer
);
132 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
138 gpio_timer_off(pinlist
[pin
].timer
);
139 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
145 gpio_timer_off(pinlist
[pin
].timer
);
147 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
152 /* Invalid pin mode */
159 void gpio_write(int pin
, uint8_t val
)
161 port_t
*p
= pinlist
[pin
].adr
;
162 uint8_t bit
= pinlist
[pin
].mask
;
164 ATOMIC_BLOCK(ATOMIC_FORCEON
) {
172 int gpio_read(int pin
)
174 port_t
*p
= pinlist
[pin
].adr
;
175 uint8_t bit
= pinlist
[pin
].mask
;
177 return (p
->pin
& bit
) != 0;
180 gpiomode_t
gpio_config_get(int pin
)
182 uint8_t timertype
= pinlist
[pin
].timer
;
184 if (timertype
& TIMER
) {
187 if (timertype
& CHANA
)
192 switch (timertype
& TIMER
) {
194 if (TCCR0A
& chan_mask
)
198 if (TCCR1A
& chan_mask
)
202 if (TCCR2A
& chan_mask
)
208 port_t
*p
= pinlist
[pin
].adr
;
209 uint8_t bit
= pinlist
[pin
].mask
;
221 * return -1: pin has no timer output
222 * 0: pin is not configured for timer output
226 long gpio_clockdiv_get(int pin
)
230 const FLASH
uint8_t *pstab
;
232 uint8_t timertype
= pinlist
[pin
].timer
;
233 if ((timertype
& TIMER
) == 0)
236 if (gpio_config_get(pin
) != OUTPUT_TIMER
)
239 switch (timertype
& TIMER
) {
256 prescale
= (prescale
& 0x07) - 1;
259 pstab
= (timertype
& TIMER
) == TIMER2
?
260 prescale_factors_2
: prescale_factors_01
;
263 divider
*= pstab
[prescale
];
265 if ((timertype
& (CHANA
|T_16BIT
)) == CHANA
)
271 int gpio_clockdiv_set(int pin
, unsigned long divider
)
276 const FLASH
uint8_t *pstab
;
278 uint8_t timertype
= pinlist
[pin
].timer
;
279 if ((timertype
& TIMER
) == 0)
286 if ((timertype
& (CHANA
|T_16BIT
)) == CHANA
)
289 if (ltop
> 1024 * ((timertype
& T_16BIT
) ? (1L<<16) : (1L<<8)))
293 pstab
= (timertype
& TIMER
) == TIMER2
?
294 prescale_factors_2
: prescale_factors_01
;
296 // debug("** clockdiv_set: pin: %d, ltop: %lu, prescale: %d\n",
297 // pin, ltop, prescale);
299 while (ltop
> ((timertype
& T_16BIT
) ? (1L<<16) : (1L<<8))) {
300 // debug("** clockdiv_set: pin: %d, ltop: %lu, prescale: %d, *pstab %d\n",
301 // pin, ltop, prescale, *pstab);
314 // PING |= _BV(0); /* Debug */
316 switch (timertype
& TIMER
) {
318 PRR0
&= ~_BV(PRTIM0
);
319 TCCR0B
= (1 << WGM02
);
322 if (timertype
& CHANA
) {
323 TCCR0A
= (PWMTOGGLE
<< COM0A0
) | (0b11 << WGM00
);
326 TCCR0A
= (PWMPOS
<< COM0B0
) | (0b11 << WGM10
);
328 TCCR0B
= (1 << WGM02
) | (prescale
<< CS10
);
332 PRR0
&= ~_BV(PRTIM1
);
333 TCCR1B
= (0b11 << WGM12
);
336 if (timertype
& CHANA
) {
338 TCCR1A
= (PWMPOS
<< COM1A0
) | (0b10 << WGM10
);
341 TCCR1A
= (PWMPOS
<< COM1B0
) | (0b10 << WGM10
);
343 // debug("pin: %d, top: %u,"
344 // " ICR1: %u, OCR1A: %u, OCR1B: %u\n",
345 // pin, top, ICR1, OCR1A, OCR1B);
347 TCCR1B
= (0b11 << WGM12
) | (prescale
<< CS10
);
351 PRR0
&= ~_BV(PRTIM2
);
352 TCCR2B
= (1 << WGM22
);
355 if (timertype
& CHANA
) {
356 TCCR2A
= (PWMTOGGLE
<< COM2A0
) | (0b11 << WGM20
);
359 TCCR2A
= (PWMPOS
<< COM2B0
) | (0b11 << WGM10
);
361 TCCR2B
= (1 << WGM22
) | (prescale
<< CS10
);
365 // PING |= _BV(0); /* Debug */
367 gpio_config(pin
, OUTPUT_TIMER
);