aboutsummaryrefslogtreecommitdiff
path: root/src/sensors/dht22.c
blob: 9653ba56fc3f0a1c0a89e4d097cf83be34d865e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <sensors/dht22.h>

#ifdef CONFIG_IOE_SENSOR_DHT22

#define PP dht22_ports[pi]
#define PPP dht22_ports[dht22_measurement.pi]

#define TIMEOUT F_CPU/40000

#define STATUS_NONE 0
#define STATUS_COMPLETE 1
#define STATUS_TIMEOUT 2

#define PORT_SENSORW 4
#define PORT_SENSORRESP_L 3
#define PORT_SENSORRESP_H 2
#define PORT_H 1
#define PORT_L 0

struct {
    uint8_t index;
    uint8_t data[5];
    volatile uint8_t status;
    uint8_t pi;
    uint8_t port_status;
} dht22_measurement;

inline void dht22_init(uint8_t pi) {
    // Set port as output and set level hight
    *(PP.DDR) |= PP.MASK;
    *(PP.PORT) |= PP.MASK;
    // Enable all pin change interrupts
    PCIFR = 0xff;
}


inline void dht22_read_deac(uint8_t status) {
    dht22_measurement.status = status;
    // Disable pin change interrupt
    *(PPP.PCMSK) &= ~PPP.PCMSK_MASK;
    timer_disable(CONFIG_IOE_SENSOR_DHT22_TIMER);
}

// This is called from pcint.c
void dht22_read_pcint(void) {
    switch (dht22_measurement.port_status) {
    case PORT_L:
        if (!(*(PPP.PIN) & PPP.MASK))
            return;
        dht22_measurement.port_status = PORT_H;
        break;
    case PORT_H:
        if (*(PPP.PIN) & PPP.MASK)
            return;
        dht22_measurement.port_status = PORT_L;
        register uint16_t val;
        val = timer_value(CONFIG_IOE_SENSOR_DHT22_TIMER);
        // TODO compare value
        if (val < 1) {
            dht22_measurement.data[dht22_measurement.index / 8]
        }
        if (++(dht22_measurement.index) == 40) {
            dht22_read_deac(STATUS_COMPLETE);
            return;
        }
        break;
    default:
        if (((*(PPP.PIN) & PPP.MASK) && dht22_measurement.port_status == 3)
            || !(*(PPP.PIN & PPP.MASK)))
            return;
        dht22_measurement.port_status--;
    }
    timer_reset(CONFIG_IOE_SENSOR_DHT22_TIMER);
}

void dht22_read_timer_overflow(void) {
    dht22_read_deac(STATUS_TIMEOUT);
}

int8_t dht22_read(uint8_t pi, struct dht22_value *rh,
                  struct dht22_value *t) {
    dht22_measurement.index = 0;
    dht22_measurement.status = STATUS_NONE;
    dht22_measurement.pi = pi;
    dht22_measurement.port_status = PORT_SENSORW;

    // Pull port down for 500us
    *(PP.PORT) &= ~PP.MASK;
    _delay_us(500);
    // Initialize timer
    timer_init(CONFIG_IOE_SENSOR_DHT22_TIMER, TIMER_DIVIDER_64);
    timer_sethook(CONFIG_IOE_SENSOR_DHT22_TIMER,
                  dht22_read_timer_overflow);
    // Set pin change interrupt
    *(PP.PCMSK) |= PP.PCMSK_MASK;
    // Set port as output and pull-up resistor
    *(PP.DDR) &= ~PP.MASK;
    *(PP.PORT) |= PP.MASK;
    // Delay till reading is done
    taskDelayTill(&(dht22_measurement.status));

    // Copy data
    rh->integral = dht22_measurement.data[0];
    rh->decimal = dht22_measurement.data[1];
    t->integral = dht22_measurement.data[2];
    t->decimal = dht22_measurement.data[3];
    // Check sum
    uint8_t sum = dht22_measurement.data[0];
    sum += dht22_measurement.data[1];
    sum += dht22_measurement.data[2];
    sum += dht22_measurement.data[3];
    if (sum != dht22_measurement.data[4])
        return 1;
    return dht22_measurement.status - 1;
}

#endif /* CONFIG_IOE_SENSOR_SHT22 */