DALI send/recv library.

Dependents:   dali_sample

DALI send/recv library

lighting control protocol.

設備照明の調光プロトコル DALI を送受信するライブラリです。

DALI インターフェースの回路図などは次を参照。

Committer:
okini3939
Date:
Mon Jul 27 05:53:55 2020 +0000
Revision:
1:319d52b5116b
Parent:
0:6cb7026982fc
bug fix;

Who changed what in which revision?

UserRevisionLine numberNew 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 1:319d52b5116b 16 #define TIME_BITTIME 833 // us, 1200bps
okini3939 1:319d52b5116b 17 #define TIME_BITTIME1p2 417 // us, 1200bps 1/2
okini3939 0:6cb7026982fc 18 #define TIME_BITTIME3p4 625 // us, 1200bps 3/4
okini3939 1:319d52b5116b 19 #define TIME_BETWEEN 10000 // us >22Te
okini3939 0:6cb7026982fc 20
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 1:319d52b5116b 42 *frame = 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 1:319d52b5116b 48 *frame = FORWARD_GROUP_IAP;
okini3939 0:6cb7026982fc 49 } else {
okini3939 1:319d52b5116b 50 *frame = 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 1:319d52b5116b 55 *frame = FORWARD_SHORT_IAP;
okini3939 0:6cb7026982fc 56 } else {
okini3939 1:319d52b5116b 57 *frame = 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 1:319d52b5116b 74 if (! busy) {
okini3939 1:319d52b5116b 75 if (mode) return; // recv working
okini3939 1:319d52b5116b 76
okini3939 1:319d52b5116b 77 _ticker.detach();
okini3939 1:319d52b5116b 78 // next data
okini3939 1:319d52b5116b 79 int dat, bit;
okini3939 1:319d52b5116b 80 busy = 1;
okini3939 1:319d52b5116b 81 send_buf->dequeue(&dat);
okini3939 1:319d52b5116b 82 bit = (dat >> 20) & 0x0fff;
okini3939 1:319d52b5116b 83 send_bit = (1 << bit) << 2;
okini3939 1:319d52b5116b 84 send_data = dat & 0x0fffff;
okini3939 1:319d52b5116b 85 halfbit = 0;
okini3939 1:319d52b5116b 86 _ticker.attach_us(this, &DALI::isr_send, TIME_BITTIME1p2);
okini3939 1:319d52b5116b 87 }
okini3939 1:319d52b5116b 88
okini3939 0:6cb7026982fc 89 if (send_bit & 3) {
okini3939 0:6cb7026982fc 90 // stop bit
okini3939 0:6cb7026982fc 91 _tx = 0;
okini3939 0:6cb7026982fc 92 } else
okini3939 0:6cb7026982fc 93 if ((halfbit == 0 && (send_data & send_bit)) || (halfbit == 1 && !(send_data & send_bit))) {
okini3939 0:6cb7026982fc 94 // low
okini3939 0:6cb7026982fc 95 _tx = 1;
okini3939 0:6cb7026982fc 96 } else {
okini3939 0:6cb7026982fc 97 // high
okini3939 0:6cb7026982fc 98 _tx = 0;
okini3939 0:6cb7026982fc 99 }
okini3939 0:6cb7026982fc 100
okini3939 0:6cb7026982fc 101 if (halfbit) {
okini3939 0:6cb7026982fc 102 halfbit = 0;
okini3939 0:6cb7026982fc 103 send_bit >>= 1;
okini3939 0:6cb7026982fc 104
okini3939 0:6cb7026982fc 105 if (send_bit == 0) {
okini3939 1:319d52b5116b 106 // end of data
okini3939 1:319d52b5116b 107 _ticker.detach();
okini3939 1:319d52b5116b 108 busy = 0;
okini3939 1:319d52b5116b 109 if (! send_buf->isEmpty()) {
okini3939 1:319d52b5116b 110 // next data
okini3939 1:319d52b5116b 111 _ticker.attach_us(this, &DALI::isr_send, TIME_BETWEEN);
okini3939 0:6cb7026982fc 112 }
okini3939 0:6cb7026982fc 113 }
okini3939 0:6cb7026982fc 114 } else {
okini3939 0:6cb7026982fc 115 halfbit = 1;
okini3939 0:6cb7026982fc 116 }
okini3939 0:6cb7026982fc 117 }
okini3939 0:6cb7026982fc 118
okini3939 1:319d52b5116b 119 int DALI::writable () {
okini3939 1:319d52b5116b 120 return ! send_buf->isFull();
okini3939 1:319d52b5116b 121 }
okini3939 1:319d52b5116b 122
okini3939 0:6cb7026982fc 123 int DALI::write (enum DALI_FRAME frame, int addr, int value) {
okini3939 0:6cb7026982fc 124 int dat, bit;
okini3939 0:6cb7026982fc 125
okini3939 0:6cb7026982fc 126 switch (frame) {
okini3939 1:319d52b5116b 127 case FORWARD_SHORT_DAP:
okini3939 0:6cb7026982fc 128 dat = (0<<15) | ((addr & 0x3f) << 9) | (0<<8) | (value & 0xff);
okini3939 0:6cb7026982fc 129 bit = 16;
okini3939 0:6cb7026982fc 130 break;
okini3939 0:6cb7026982fc 131
okini3939 1:319d52b5116b 132 case FORWARD_SHORT_IAP:
okini3939 0:6cb7026982fc 133 dat = (0<<15) | ((addr & 0x3f) << 9) | (1<<8) | (value & 0xff);
okini3939 0:6cb7026982fc 134 bit = 16;
okini3939 0:6cb7026982fc 135 break;
okini3939 0:6cb7026982fc 136
okini3939 1:319d52b5116b 137 case FORWARD_GROUP_DAP:
okini3939 0:6cb7026982fc 138 dat = (1<<15) | ((addr & 0x3f) << 9) | (0<<8) | (value & 0xff);
okini3939 0:6cb7026982fc 139 bit = 16;
okini3939 0:6cb7026982fc 140 break;
okini3939 0:6cb7026982fc 141
okini3939 1:319d52b5116b 142 case FORWARD_GROUP_IAP:
okini3939 0:6cb7026982fc 143 dat = (1<<15) | ((addr & 0x3f) << 9) | (1<<8) | (value & 0xff);
okini3939 0:6cb7026982fc 144 bit = 16;
okini3939 0:6cb7026982fc 145 break;
okini3939 0:6cb7026982fc 146
okini3939 1:319d52b5116b 147 case BACKWARD:
okini3939 0:6cb7026982fc 148 dat = (value & 0xff);
okini3939 0:6cb7026982fc 149 bit = 8;
okini3939 0:6cb7026982fc 150 break;
okini3939 0:6cb7026982fc 151
okini3939 0:6cb7026982fc 152 default:
okini3939 0:6cb7026982fc 153 return -1;
okini3939 0:6cb7026982fc 154 }
okini3939 0:6cb7026982fc 155
okini3939 0:6cb7026982fc 156 dat = ((1<<bit) | dat) << 2; // start bit
okini3939 0:6cb7026982fc 157 dat |= bit << 20;
okini3939 0:6cb7026982fc 158 send_buf->queue(dat);
okini3939 0:6cb7026982fc 159
okini3939 0:6cb7026982fc 160 if (! busy) {
okini3939 1:319d52b5116b 161 while (mode); // wait recv
okini3939 1:319d52b5116b 162 // begin data
okini3939 0:6cb7026982fc 163 busy = 1;
okini3939 0:6cb7026982fc 164 send_buf->dequeue(&dat);
okini3939 0:6cb7026982fc 165 bit = (dat >> 20) & 0x0fff;
okini3939 0:6cb7026982fc 166 send_bit = (1 << bit) << 2;
okini3939 0:6cb7026982fc 167 send_data = dat & 0x0fffff;
okini3939 0:6cb7026982fc 168 halfbit = 0;
okini3939 0:6cb7026982fc 169 _ticker.attach_us(this, &DALI::isr_send, TIME_BITTIME1p2);
okini3939 0:6cb7026982fc 170 }
okini3939 0:6cb7026982fc 171 return 0;
okini3939 0:6cb7026982fc 172 }
okini3939 0:6cb7026982fc 173
okini3939 0:6cb7026982fc 174 void DALI::isr_rx () {
okini3939 0:6cb7026982fc 175
okini3939 0:6cb7026982fc 176 if (timeflg || busy) return;
okini3939 0:6cb7026982fc 177
okini3939 0:6cb7026982fc 178 timeflg = 1;
okini3939 0:6cb7026982fc 179 _timer.detach();
okini3939 0:6cb7026982fc 180 _timer.attach_us(this, &DALI::isr_timer, TIME_BITTIME3p4);
okini3939 0:6cb7026982fc 181
okini3939 0:6cb7026982fc 182 if (_rx.read() && mode == 0) {
okini3939 0:6cb7026982fc 183 // start bit
okini3939 0:6cb7026982fc 184 mode ++;
okini3939 0:6cb7026982fc 185 recv_data = 0;
okini3939 0:6cb7026982fc 186 recv_bit = 0x8000;
okini3939 0:6cb7026982fc 187 }
okini3939 0:6cb7026982fc 188 }
okini3939 0:6cb7026982fc 189
okini3939 0:6cb7026982fc 190 void DALI::isr_timer () {
okini3939 0:6cb7026982fc 191 timeflg = 0;
okini3939 0:6cb7026982fc 192 _timer.detach();
okini3939 0:6cb7026982fc 193 _timer.attach_us(this, &DALI::isr_timeout, TIME_BITTIME);
okini3939 0:6cb7026982fc 194
okini3939 0:6cb7026982fc 195 if (recv_bit) {
okini3939 0:6cb7026982fc 196 // data bit
okini3939 0:6cb7026982fc 197 if (_rx.read()) {
okini3939 0:6cb7026982fc 198 // high
okini3939 0:6cb7026982fc 199 recv_data |= recv_bit;
okini3939 0:6cb7026982fc 200 } else {
okini3939 0:6cb7026982fc 201 // low
okini3939 0:6cb7026982fc 202 recv_data &= ~recv_bit;
okini3939 0:6cb7026982fc 203 }
okini3939 0:6cb7026982fc 204 recv_bit >>= 1;
okini3939 0:6cb7026982fc 205 } else
okini3939 0:6cb7026982fc 206 if (mode == 1) {
okini3939 0:6cb7026982fc 207 if (_rx.read()) {
okini3939 0:6cb7026982fc 208 // error
okini3939 0:6cb7026982fc 209 mode = 0;
okini3939 0:6cb7026982fc 210 } else {
okini3939 0:6cb7026982fc 211 // stop bit 1
okini3939 0:6cb7026982fc 212 mode ++;
okini3939 0:6cb7026982fc 213 }
okini3939 0:6cb7026982fc 214 }
okini3939 0:6cb7026982fc 215 }
okini3939 0:6cb7026982fc 216
okini3939 0:6cb7026982fc 217 void DALI::isr_timeout () {
okini3939 0:6cb7026982fc 218 timeflg = 0;
okini3939 0:6cb7026982fc 219 _timer.detach();
okini3939 0:6cb7026982fc 220
okini3939 0:6cb7026982fc 221 if (recv_bit) {
okini3939 0:6cb7026982fc 222 // Backward frame (8bit)
okini3939 0:6cb7026982fc 223 if (mode == 1 && _rx.read() == 0 && !(recv_data & (1<<7))) {
okini3939 0:6cb7026982fc 224 // stop bit 2
okini3939 0:6cb7026982fc 225 recv_data = (1<<16) | (recv_data >> 8);
okini3939 0:6cb7026982fc 226 recv_buf->queue(recv_data);
okini3939 0:6cb7026982fc 227 mode = 0;
okini3939 0:6cb7026982fc 228 } else {
okini3939 0:6cb7026982fc 229 mode = 0;
okini3939 0:6cb7026982fc 230 }
okini3939 0:6cb7026982fc 231 } else {
okini3939 0:6cb7026982fc 232 // Forward frame (16bit)
okini3939 0:6cb7026982fc 233 if (mode == 2 && _rx.read() == 0) {
okini3939 0:6cb7026982fc 234 // stop bit 2
okini3939 0:6cb7026982fc 235 recv_buf->queue(recv_data);
okini3939 0:6cb7026982fc 236 mode = 0;
okini3939 0:6cb7026982fc 237 } else {
okini3939 0:6cb7026982fc 238 mode = 0;
okini3939 0:6cb7026982fc 239 }
okini3939 0:6cb7026982fc 240 }
okini3939 0:6cb7026982fc 241 }