Root/atusb/fw/board_app.c

Source at commit f7b9a18917b8ed913f33bda55a33a87cf419c352 created 8 years 4 months ago.
By Werner Almesberger, atusb/fw/: new request ATUSB_GPIO_CLEANUP to re-enable INT0
1/*
2 * fw/board_app.c - Board-specific functions (for the application)
3 *
4 * Written 2011 by Werner Almesberger
5 * Copyright 2011 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <stddef.h>
15#include <stdint.h>
16
17#include <avr/io.h>
18#include <avr/interrupt.h>
19
20#define F_CPU 8000000UL
21#include <util/delay.h>
22
23#include "usb.h"
24#include "at86rf230.h"
25#include "board.h"
26#include "spi.h"
27
28
29static volatile uint32_t timer_h = 0; /* 2^(16+32) / 8 MHz = ~1.1 years */
30
31
32void reset_cpu(void)
33{
34    WDTCSR = 1 << WDE;
35}
36
37
38uint8_t read_irq(void)
39{
40    return PIN(IRQ_RF);
41}
42
43
44void slp_tr(void)
45{
46    SET(SLP_TR);
47    CLR(SLP_TR);
48}
49
50
51ISR(TIMER1_OVF_vect)
52{
53    timer_h++;
54}
55
56
57uint64_t timer_read(void)
58{
59    uint32_t high;
60    uint8_t low, mid;
61
62    do {
63        if (TIFR1 & (1 << TOV1)) {
64            TIFR1 = 1 << TOV1;
65            timer_h++;
66        }
67        high = timer_h;
68        low = TCNT1L;
69        mid = TCNT1H;
70    }
71    while (TIFR1 & (1 << TOV1));
72
73    /*
74     * We need all these casts because the intermediate results are handled
75     * as if they were signed and thus get sign-expanded. Sounds wrong-ish.
76     */
77    return (uint64_t) high << 16 | (uint64_t) mid << 8 | (uint64_t) low;
78}
79
80
81void timer_init(void)
82{
83    /* configure timer 1 as a free-running CLK counter */
84
85    TCCR1A = 0;
86    TCCR1B = 1 << CS10;
87
88    /* enable timer overflow interrupt */
89
90    TIMSK1 = 1 << TOIE1;
91}
92
93
94int gpio(uint8_t port, uint8_t data, uint8_t dir, uint8_t mask, uint8_t *res)
95{
96    EIMSK = 0; /* recover INT_RF to ATUSB_GPIO_CLEANUP or an MCU reset */
97
98    switch (port) {
99    case 1:
100        DDRB = (DDRB & ~mask) | dir;
101        PORTB = (PORTB & ~mask) | data;
102        break;
103    case 2:
104        DDRC = (DDRC & ~mask) | dir;
105        PORTC = (PORTC & ~mask) | data;
106        break;
107    case 3:
108        DDRD = (DDRD & ~mask) | dir;
109        PORTD = (PORTD & ~mask) | data;
110        break;
111    default:
112        return 0;
113    }
114
115    /* disable the UART so that we can meddle with these pins as well. */
116    spi_off();
117    _delay_ms(1);
118
119    switch (port) {
120    case 1:
121        res[0] = PINB;
122        res[1] = PORTB;
123        res[2] = DDRB;
124        break;
125    case 2:
126        res[0] = PINC;
127        res[1] = PORTC;
128        res[2] = DDRC;
129        break;
130    case 3:
131        res[0] = PIND;
132        res[1] = PORTD;
133        res[2] = DDRD;
134        break;
135    }
136
137    return 1;
138}
139
140
141void gpio_cleanup(void)
142{
143    EIMSK = 1 << 0;
144}
145
146
147ISR(INT0_vect)
148{
149    static uint8_t irq;
150
151    if (eps[1].state != EP_IDLE)
152        return;
153    spi_begin();
154    spi_send(AT86RF230_REG_READ | REG_IRQ_STATUS);
155    irq = spi_recv();
156    spi_end();
157    usb_send(&eps[1], &irq, 1, NULL, NULL);
158}
159
160
161void board_app_init(void)
162{
163    /* enable INT0, trigger on rising edge */
164    EICRA = 1 << ISC01 | 1 << ISC00;
165    EIMSK = 1 << 0;
166}
167

Archive Download this file



interactive