DALI send/recv library.
DALI send/recv library
lighting control protocol.
設備照明の調光プロトコル DALI を送受信するライブラリです。
DALI インターフェースの回路図などは次を参照。
- http://ww1.microchip.com/downloads/jp/AppNotes/01465A_JP.pdf
- https://www.mouser.com/pdfdocs/AN11174.pdf
DALI.cpp@0:6cb7026982fc, 2020-07-22 (annotated)
- Committer:
- okini3939
- Date:
- Wed Jul 22 03:04:04 2020 +0000
- Revision:
- 0:6cb7026982fc
- Child:
- 1:319d52b5116b
1st build;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
okini3939 | 0:6cb7026982fc | 1 | /* |
okini3939 | 0:6cb7026982fc | 2 | * DALI send/recv library |
okini3939 | 0:6cb7026982fc | 3 | * Copyright (c) 2020 Hiroshi Suga |
okini3939 | 0:6cb7026982fc | 4 | * Released under the MIT License: http://mbed.org/license/mit |
okini3939 | 0:6cb7026982fc | 5 | */ |
okini3939 | 0:6cb7026982fc | 6 | |
okini3939 | 0:6cb7026982fc | 7 | /** @file |
okini3939 | 0:6cb7026982fc | 8 | * @brief DALI send/recv |
okini3939 | 0:6cb7026982fc | 9 | */ |
okini3939 | 0:6cb7026982fc | 10 | |
okini3939 | 0:6cb7026982fc | 11 | #include "mbed.h" |
okini3939 | 0:6cb7026982fc | 12 | #include "DALI.h" |
okini3939 | 0:6cb7026982fc | 13 | |
okini3939 | 0:6cb7026982fc | 14 | #define BUFFER_SIZE 20 |
okini3939 | 0:6cb7026982fc | 15 | |
okini3939 | 0:6cb7026982fc | 16 | #define TIME_BITTIME 833 // us, 1200bps |
okini3939 | 0:6cb7026982fc | 17 | #define TIME_BITTIME1p2 417 // us, 1200bps 3/4 |
okini3939 | 0:6cb7026982fc | 18 | #define TIME_BITTIME3p4 625 // us, 1200bps 3/4 |
okini3939 | 0:6cb7026982fc | 19 | |
okini3939 | 0:6cb7026982fc | 20 | extern Serial pc; |
okini3939 | 0:6cb7026982fc | 21 | |
okini3939 | 0:6cb7026982fc | 22 | DALI::DALI (PinName tx, PinName rx) : _tx(tx), _rx(rx) { |
okini3939 | 0:6cb7026982fc | 23 | _rx.mode(PullUp); |
okini3939 | 0:6cb7026982fc | 24 | _rx.fall(this, &DALI::isr_rx); |
okini3939 | 0:6cb7026982fc | 25 | _rx.rise(this, &DALI::isr_rx); |
okini3939 | 0:6cb7026982fc | 26 | _tx = 0; |
okini3939 | 0:6cb7026982fc | 27 | |
okini3939 | 0:6cb7026982fc | 28 | recv_buf = new CircBuffer<int>(BUFFER_SIZE); |
okini3939 | 0:6cb7026982fc | 29 | send_buf = new CircBuffer<int>(BUFFER_SIZE); |
okini3939 | 0:6cb7026982fc | 30 | |
okini3939 | 0:6cb7026982fc | 31 | mode = 0; |
okini3939 | 0:6cb7026982fc | 32 | count = 0; |
okini3939 | 0:6cb7026982fc | 33 | timeflg = 0; |
okini3939 | 0:6cb7026982fc | 34 | busy = 0; |
okini3939 | 0:6cb7026982fc | 35 | } |
okini3939 | 0:6cb7026982fc | 36 | |
okini3939 | 0:6cb7026982fc | 37 | int DALI::read (enum DALI_FRAME *frame, int *addr, int *value) { |
okini3939 | 0:6cb7026982fc | 38 | int dat; |
okini3939 | 0:6cb7026982fc | 39 | |
okini3939 | 0:6cb7026982fc | 40 | if (recv_buf->dequeue(&dat)) { |
okini3939 | 0:6cb7026982fc | 41 | if (dat & (1<<16)) { |
okini3939 | 0:6cb7026982fc | 42 | *frame = DALI_BACKWARD; |
okini3939 | 0:6cb7026982fc | 43 | *value = dat & 0xff; |
okini3939 | 0:6cb7026982fc | 44 | } else { |
okini3939 | 0:6cb7026982fc | 45 | if (dat & (1<<15)) { |
okini3939 | 0:6cb7026982fc | 46 | // group |
okini3939 | 0:6cb7026982fc | 47 | if (dat & (1<<8)) { |
okini3939 | 0:6cb7026982fc | 48 | *frame = DALI_FORWARD_GROUP_IAP; |
okini3939 | 0:6cb7026982fc | 49 | } else { |
okini3939 | 0:6cb7026982fc | 50 | *frame = DALI_FORWARD_GROUP_DAP; |
okini3939 | 0:6cb7026982fc | 51 | } |
okini3939 | 0:6cb7026982fc | 52 | } else { |
okini3939 | 0:6cb7026982fc | 53 | // short |
okini3939 | 0:6cb7026982fc | 54 | if (dat & (1<<8)) { |
okini3939 | 0:6cb7026982fc | 55 | *frame = DALI_FORWARD_SHORT_IAP; |
okini3939 | 0:6cb7026982fc | 56 | } else { |
okini3939 | 0:6cb7026982fc | 57 | *frame = DALI_FORWARD_SHORT_DAP; |
okini3939 | 0:6cb7026982fc | 58 | } |
okini3939 | 0:6cb7026982fc | 59 | } |
okini3939 | 0:6cb7026982fc | 60 | *addr = (dat >> 9) & 0x3f; |
okini3939 | 0:6cb7026982fc | 61 | *value = dat & 0xff; |
okini3939 | 0:6cb7026982fc | 62 | } |
okini3939 | 0:6cb7026982fc | 63 | return 0; |
okini3939 | 0:6cb7026982fc | 64 | } |
okini3939 | 0:6cb7026982fc | 65 | return -1; |
okini3939 | 0:6cb7026982fc | 66 | } |
okini3939 | 0:6cb7026982fc | 67 | |
okini3939 | 0:6cb7026982fc | 68 | int DALI::readable () { |
okini3939 | 0:6cb7026982fc | 69 | return ! recv_buf->isEmpty(); |
okini3939 | 0:6cb7026982fc | 70 | } |
okini3939 | 0:6cb7026982fc | 71 | |
okini3939 | 0:6cb7026982fc | 72 | void DALI::isr_send () { |
okini3939 | 0:6cb7026982fc | 73 | |
okini3939 | 0:6cb7026982fc | 74 | if (send_bit & 3) { |
okini3939 | 0:6cb7026982fc | 75 | // stop bit |
okini3939 | 0:6cb7026982fc | 76 | _tx = 0; |
okini3939 | 0:6cb7026982fc | 77 | } else |
okini3939 | 0:6cb7026982fc | 78 | if ((halfbit == 0 && (send_data & send_bit)) || (halfbit == 1 && !(send_data & send_bit))) { |
okini3939 | 0:6cb7026982fc | 79 | // low |
okini3939 | 0:6cb7026982fc | 80 | _tx = 1; |
okini3939 | 0:6cb7026982fc | 81 | } else { |
okini3939 | 0:6cb7026982fc | 82 | // high |
okini3939 | 0:6cb7026982fc | 83 | _tx = 0; |
okini3939 | 0:6cb7026982fc | 84 | } |
okini3939 | 0:6cb7026982fc | 85 | |
okini3939 | 0:6cb7026982fc | 86 | if (halfbit) { |
okini3939 | 0:6cb7026982fc | 87 | halfbit = 0; |
okini3939 | 0:6cb7026982fc | 88 | send_bit >>= 1; |
okini3939 | 0:6cb7026982fc | 89 | |
okini3939 | 0:6cb7026982fc | 90 | if (send_bit == 0) { |
okini3939 | 0:6cb7026982fc | 91 | if (send_buf->isEmpty()) { |
okini3939 | 0:6cb7026982fc | 92 | // end |
okini3939 | 0:6cb7026982fc | 93 | _ticker.detach(); |
okini3939 | 0:6cb7026982fc | 94 | busy = 0; |
okini3939 | 0:6cb7026982fc | 95 | } else { |
okini3939 | 0:6cb7026982fc | 96 | // next |
okini3939 | 0:6cb7026982fc | 97 | int dat, bit; |
okini3939 | 0:6cb7026982fc | 98 | send_buf->dequeue(&dat); |
okini3939 | 0:6cb7026982fc | 99 | bit = (dat >> 20) & 0x0fff; |
okini3939 | 0:6cb7026982fc | 100 | send_bit = (1 << bit) << 2; |
okini3939 | 0:6cb7026982fc | 101 | send_data = dat & 0x0fffff; |
okini3939 | 0:6cb7026982fc | 102 | halfbit = 0; |
okini3939 | 0:6cb7026982fc | 103 | } |
okini3939 | 0:6cb7026982fc | 104 | } |
okini3939 | 0:6cb7026982fc | 105 | } else { |
okini3939 | 0:6cb7026982fc | 106 | halfbit = 1; |
okini3939 | 0:6cb7026982fc | 107 | } |
okini3939 | 0:6cb7026982fc | 108 | } |
okini3939 | 0:6cb7026982fc | 109 | |
okini3939 | 0:6cb7026982fc | 110 | int DALI::write (enum DALI_FRAME frame, int addr, int value) { |
okini3939 | 0:6cb7026982fc | 111 | int dat, bit; |
okini3939 | 0:6cb7026982fc | 112 | |
okini3939 | 0:6cb7026982fc | 113 | while ((volatile int)send_bit); |
okini3939 | 0:6cb7026982fc | 114 | |
okini3939 | 0:6cb7026982fc | 115 | switch (frame) { |
okini3939 | 0:6cb7026982fc | 116 | case DALI_FORWARD_SHORT_DAP: |
okini3939 | 0:6cb7026982fc | 117 | dat = (0<<15) | ((addr & 0x3f) << 9) | (0<<8) | (value & 0xff); |
okini3939 | 0:6cb7026982fc | 118 | bit = 16; |
okini3939 | 0:6cb7026982fc | 119 | break; |
okini3939 | 0:6cb7026982fc | 120 | |
okini3939 | 0:6cb7026982fc | 121 | case DALI_FORWARD_SHORT_IAP: |
okini3939 | 0:6cb7026982fc | 122 | dat = (0<<15) | ((addr & 0x3f) << 9) | (1<<8) | (value & 0xff); |
okini3939 | 0:6cb7026982fc | 123 | bit = 16; |
okini3939 | 0:6cb7026982fc | 124 | break; |
okini3939 | 0:6cb7026982fc | 125 | |
okini3939 | 0:6cb7026982fc | 126 | case DALI_FORWARD_GROUP_DAP: |
okini3939 | 0:6cb7026982fc | 127 | dat = (1<<15) | ((addr & 0x3f) << 9) | (0<<8) | (value & 0xff); |
okini3939 | 0:6cb7026982fc | 128 | bit = 16; |
okini3939 | 0:6cb7026982fc | 129 | break; |
okini3939 | 0:6cb7026982fc | 130 | |
okini3939 | 0:6cb7026982fc | 131 | case DALI_FORWARD_GROUP_IAP: |
okini3939 | 0:6cb7026982fc | 132 | dat = (1<<15) | ((addr & 0x3f) << 9) | (1<<8) | (value & 0xff); |
okini3939 | 0:6cb7026982fc | 133 | bit = 16; |
okini3939 | 0:6cb7026982fc | 134 | break; |
okini3939 | 0:6cb7026982fc | 135 | |
okini3939 | 0:6cb7026982fc | 136 | case DALI_BACKWARD: |
okini3939 | 0:6cb7026982fc | 137 | dat = (value & 0xff); |
okini3939 | 0:6cb7026982fc | 138 | bit = 8; |
okini3939 | 0:6cb7026982fc | 139 | break; |
okini3939 | 0:6cb7026982fc | 140 | |
okini3939 | 0:6cb7026982fc | 141 | default: |
okini3939 | 0:6cb7026982fc | 142 | return -1; |
okini3939 | 0:6cb7026982fc | 143 | } |
okini3939 | 0:6cb7026982fc | 144 | |
okini3939 | 0:6cb7026982fc | 145 | dat = ((1<<bit) | dat) << 2; // start bit |
okini3939 | 0:6cb7026982fc | 146 | dat |= bit << 20; |
okini3939 | 0:6cb7026982fc | 147 | send_buf->queue(dat); |
okini3939 | 0:6cb7026982fc | 148 | |
okini3939 | 0:6cb7026982fc | 149 | if (! busy) { |
okini3939 | 0:6cb7026982fc | 150 | busy = 1; |
okini3939 | 0:6cb7026982fc | 151 | send_buf->dequeue(&dat); |
okini3939 | 0:6cb7026982fc | 152 | bit = (dat >> 20) & 0x0fff; |
okini3939 | 0:6cb7026982fc | 153 | send_bit = (1 << bit) << 2; |
okini3939 | 0:6cb7026982fc | 154 | send_data = dat & 0x0fffff; |
okini3939 | 0:6cb7026982fc | 155 | halfbit = 0; |
okini3939 | 0:6cb7026982fc | 156 | _ticker.attach_us(this, &DALI::isr_send, TIME_BITTIME1p2); |
okini3939 | 0:6cb7026982fc | 157 | } |
okini3939 | 0:6cb7026982fc | 158 | return 0; |
okini3939 | 0:6cb7026982fc | 159 | } |
okini3939 | 0:6cb7026982fc | 160 | |
okini3939 | 0:6cb7026982fc | 161 | void DALI::isr_rx () { |
okini3939 | 0:6cb7026982fc | 162 | |
okini3939 | 0:6cb7026982fc | 163 | if (timeflg || busy) return; |
okini3939 | 0:6cb7026982fc | 164 | |
okini3939 | 0:6cb7026982fc | 165 | timeflg = 1; |
okini3939 | 0:6cb7026982fc | 166 | _timer.detach(); |
okini3939 | 0:6cb7026982fc | 167 | _timer.attach_us(this, &DALI::isr_timer, TIME_BITTIME3p4); |
okini3939 | 0:6cb7026982fc | 168 | |
okini3939 | 0:6cb7026982fc | 169 | if (_rx.read() && mode == 0) { |
okini3939 | 0:6cb7026982fc | 170 | // start bit |
okini3939 | 0:6cb7026982fc | 171 | mode ++; |
okini3939 | 0:6cb7026982fc | 172 | recv_data = 0; |
okini3939 | 0:6cb7026982fc | 173 | recv_bit = 0x8000; |
okini3939 | 0:6cb7026982fc | 174 | } |
okini3939 | 0:6cb7026982fc | 175 | } |
okini3939 | 0:6cb7026982fc | 176 | |
okini3939 | 0:6cb7026982fc | 177 | void DALI::isr_timer () { |
okini3939 | 0:6cb7026982fc | 178 | timeflg = 0; |
okini3939 | 0:6cb7026982fc | 179 | _timer.detach(); |
okini3939 | 0:6cb7026982fc | 180 | _timer.attach_us(this, &DALI::isr_timeout, TIME_BITTIME); |
okini3939 | 0:6cb7026982fc | 181 | |
okini3939 | 0:6cb7026982fc | 182 | if (recv_bit) { |
okini3939 | 0:6cb7026982fc | 183 | // data bit |
okini3939 | 0:6cb7026982fc | 184 | if (_rx.read()) { |
okini3939 | 0:6cb7026982fc | 185 | // high |
okini3939 | 0:6cb7026982fc | 186 | recv_data |= recv_bit; |
okini3939 | 0:6cb7026982fc | 187 | } else { |
okini3939 | 0:6cb7026982fc | 188 | // low |
okini3939 | 0:6cb7026982fc | 189 | recv_data &= ~recv_bit; |
okini3939 | 0:6cb7026982fc | 190 | } |
okini3939 | 0:6cb7026982fc | 191 | recv_bit >>= 1; |
okini3939 | 0:6cb7026982fc | 192 | } else |
okini3939 | 0:6cb7026982fc | 193 | if (mode == 1) { |
okini3939 | 0:6cb7026982fc | 194 | if (_rx.read()) { |
okini3939 | 0:6cb7026982fc | 195 | // error |
okini3939 | 0:6cb7026982fc | 196 | mode = 0; |
okini3939 | 0:6cb7026982fc | 197 | } else { |
okini3939 | 0:6cb7026982fc | 198 | // stop bit 1 |
okini3939 | 0:6cb7026982fc | 199 | mode ++; |
okini3939 | 0:6cb7026982fc | 200 | } |
okini3939 | 0:6cb7026982fc | 201 | } |
okini3939 | 0:6cb7026982fc | 202 | } |
okini3939 | 0:6cb7026982fc | 203 | |
okini3939 | 0:6cb7026982fc | 204 | void DALI::isr_timeout () { |
okini3939 | 0:6cb7026982fc | 205 | timeflg = 0; |
okini3939 | 0:6cb7026982fc | 206 | _timer.detach(); |
okini3939 | 0:6cb7026982fc | 207 | |
okini3939 | 0:6cb7026982fc | 208 | if (recv_bit) { |
okini3939 | 0:6cb7026982fc | 209 | // Backward frame (8bit) |
okini3939 | 0:6cb7026982fc | 210 | if (mode == 1 && _rx.read() == 0 && !(recv_data & (1<<7))) { |
okini3939 | 0:6cb7026982fc | 211 | // stop bit 2 |
okini3939 | 0:6cb7026982fc | 212 | recv_data = (1<<16) | (recv_data >> 8); |
okini3939 | 0:6cb7026982fc | 213 | recv_buf->queue(recv_data); |
okini3939 | 0:6cb7026982fc | 214 | mode = 0; |
okini3939 | 0:6cb7026982fc | 215 | } else { |
okini3939 | 0:6cb7026982fc | 216 | mode = 0; |
okini3939 | 0:6cb7026982fc | 217 | } |
okini3939 | 0:6cb7026982fc | 218 | } else { |
okini3939 | 0:6cb7026982fc | 219 | // Forward frame (16bit) |
okini3939 | 0:6cb7026982fc | 220 | if (mode == 2 && _rx.read() == 0) { |
okini3939 | 0:6cb7026982fc | 221 | // stop bit 2 |
okini3939 | 0:6cb7026982fc | 222 | recv_buf->queue(recv_data); |
okini3939 | 0:6cb7026982fc | 223 | mode = 0; |
okini3939 | 0:6cb7026982fc | 224 | } else { |
okini3939 | 0:6cb7026982fc | 225 | mode = 0; |
okini3939 | 0:6cb7026982fc | 226 | } |
okini3939 | 0:6cb7026982fc | 227 | } |
okini3939 | 0:6cb7026982fc | 228 | } |