]>
cloudbase.mooo.com Git - z180-stamp.git/blob - avr/pin.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
25 pre Timer0 Timer1 Timer2
26 --------------------------------------------------
32 5 1024 x4 1024 x4 128 x2
35 --------------------------------------------------
40 #define PWMTOGGLE 0b01
45 const FLASH
uint8_t prescale_factors_01
[] =
48 const FLASH
uint8_t prescale_factors_2
[] =
49 { 8, 4, 2, 2, 2, 4, 0 };
51 typedef volatile struct {
61 #define TIMER0 (1 << 0)
62 #define TIMER1 (2 << 0)
63 #define TIMER2 (3 << 0)
64 #define TIMER (3 << 0)
65 #define T_16BIT (1 << 3)
66 #define CHANA (1 << 4)
67 #define CHANB (0 << 4)
72 const FLASH
struct pindef_s pinlist
[PIN_MAX
] = {
73 { (port_t
*) &PING
, _BV(5), TIMER0
| CHANB
},
74 { (port_t
*) &PING
, _BV(4), NO_TIMER
},
75 { (port_t
*) &PINB
, _BV(4), TIMER2
| CHANA
},
76 { (port_t
*) &PINB
, _BV(5), TIMER1
| CHANA
| T_16BIT
},
77 { (port_t
*) &PINB
, _BV(6), TIMER1
| CHANB
| T_16BIT
},
78 { (port_t
*) &PINB
, _BV(7), TIMER0
| CHANA
},
79 { (port_t
*) &PING
, _BV(3), NO_TIMER
},
80 { (port_t
*) &PING
, _BV(2), NO_TIMER
},
81 { (port_t
*) &PING
, _BV(1), NO_TIMER
},
82 { (port_t
*) &PING
, _BV(0), NO_TIMER
},
83 { (port_t
*) &PINE
, _BV(7), NO_TIMER
},
86 void pin_timer_off(uint8_t timertype
)
90 if (timertype
& CHANA
)
95 switch (timertype
& TIMER
) {
97 if (TCCR0A
& chan_mask
) {
104 if (TCCR1A
& chan_mask
) {
111 if (TCCR2A
& chan_mask
) {
120 int pin_config(int pin
, pinmode_t mode
)
122 if ((unsigned) pin
>= ARRAY_SIZE(pinlist
)) {
123 /* Invalid pin number */
127 port_t
*p
= pinlist
[pin
].adr
;
128 uint8_t bit
= pinlist
[pin
].mask
;
132 pin_timer_off(pinlist
[pin
].timer
);
133 ATOMIC_BLOCK(ATOMIC_RESTORESTATE
) {
139 pin_timer_off(pinlist
[pin
].timer
);
140 ATOMIC_BLOCK(ATOMIC_RESTORESTATE
) {
146 pin_timer_off(pinlist
[pin
].timer
);
148 ATOMIC_BLOCK(ATOMIC_RESTORESTATE
) {
153 /* Invalid pin mode */
160 void pin_write(int pin
, uint8_t val
)
162 port_t
*p
= pinlist
[pin
].adr
;
163 uint8_t bit
= pinlist
[pin
].mask
;
165 ATOMIC_BLOCK(ATOMIC_RESTORESTATE
) {
173 int pin_read(int pin
)
175 port_t
*p
= pinlist
[pin
].adr
;
176 uint8_t bit
= pinlist
[pin
].mask
;
178 return (p
->pin
& bit
) != 0;
181 pinmode_t
pin_config_get(int pin
)
183 uint8_t timertype
= pinlist
[pin
].timer
;
185 if (timertype
& TIMER
) {
188 if (timertype
& CHANA
)
193 switch (timertype
& TIMER
) {
195 if (TCCR0A
& chan_mask
)
199 if (TCCR1A
& chan_mask
)
203 if (TCCR2A
& chan_mask
)
209 port_t
*p
= pinlist
[pin
].adr
;
210 uint8_t bit
= pinlist
[pin
].mask
;
222 * return -1: pin has no timer output
223 * 0: pin is not configured for timer output
227 long pin_clockdiv_get(int pin
)
231 const FLASH
uint8_t *pstab
;
233 uint8_t timertype
= pinlist
[pin
].timer
;
234 if ((timertype
& TIMER
) == 0)
237 if (pin_config_get(pin
) != OUTPUT_TIMER
)
240 switch (timertype
& TIMER
) {
257 prescale
= (prescale
& 0x07) - 1;
260 pstab
= (timertype
& TIMER
) == TIMER2
?
261 prescale_factors_2
: prescale_factors_01
;
264 divider
*= pstab
[prescale
];
266 if ((timertype
& (CHANA
|T_16BIT
)) == CHANA
)
272 int pin_clockdiv_set(int pin
, unsigned long divider
)
277 const FLASH
uint8_t *pstab
;
279 uint8_t timertype
= pinlist
[pin
].timer
;
280 if ((timertype
& TIMER
) == 0)
287 if ((timertype
& (CHANA
|T_16BIT
)) == CHANA
)
290 if (ltop
> 1024 * ((timertype
& T_16BIT
) ? (1L<<16) : (1L<<8)))
294 pstab
= (timertype
& TIMER
) == TIMER2
?
295 prescale_factors_2
: prescale_factors_01
;
297 // debug("** clockdiv_set: pin: %d, ltop: %lu, prescale: %d\n",
298 // pin, ltop, prescale);
300 while (ltop
> ((timertype
& T_16BIT
) ? (1L<<16) : (1L<<8))) {
301 // debug("** clockdiv_set: pin: %d, ltop: %lu, prescale: %d, *pstab %d\n",
302 // pin, ltop, prescale, *pstab);
315 PING
|= _BV(0); /* Debug */
317 switch (timertype
& TIMER
) {
319 PRR0
&= ~_BV(PRTIM0
);
320 TCCR0B
= (1 << WGM02
);
323 if (timertype
& CHANA
) {
324 TCCR0A
= (PWMTOGGLE
<< COM0A0
) | (0b11 << WGM00
);
327 TCCR0A
= (PWMPOS
<< COM0B0
) | (0b11 << WGM10
);
329 TCCR0B
= (1 << WGM02
) | (prescale
<< CS10
);
333 PRR0
&= ~_BV(PRTIM1
);
334 TCCR1B
= (0b11 << WGM12
);
337 if (timertype
& CHANA
) {
339 TCCR1A
= (PWMPOS
<< COM1A0
) | (0b10 << WGM10
);
342 TCCR1A
= (PWMPOS
<< COM1B0
) | (0b10 << WGM10
);
344 // debug("pin: %d, top: %u,"
345 // " ICR1: %u, OCR1A: %u, OCR1B: %u\n",
346 // pin, top, ICR1, OCR1A, OCR1B);
348 TCCR1B
= (0b11 << WGM12
) | (prescale
<< CS10
);
352 PRR0
&= ~_BV(PRTIM2
);
353 TCCR2B
= (1 << WGM22
);
356 if (timertype
& CHANA
) {
357 TCCR2A
= (PWMTOGGLE
<< COM2A0
) | (0b11 << WGM20
);
360 TCCR2A
= (PWMPOS
<< COM2B0
) | (0b11 << WGM10
);
362 TCCR2B
= (1 << WGM22
) | (prescale
<< CS10
);
366 PING
|= _BV(0); /* Debug */
368 pin_config(pin
, OUTPUT_TIMER
);