DALI send/recv library.

Dependents:   dali_sample

DALI send/recv library

lighting control protocol.

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

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

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?

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 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 }