DALI send/recv library.
Embed:
(wiki syntax)
Show/hide line numbers
DALI.cpp
Go to the documentation of this file.
00001 /* 00002 * DALI send/recv library 00003 * Copyright (c) 2020 Hiroshi Suga 00004 * Released under the MIT License: http://mbed.org/license/mit 00005 */ 00006 00007 /** @file 00008 * @brief DALI send/recv 00009 */ 00010 00011 #include "mbed.h" 00012 #include "DALI.h" 00013 00014 #define BUFFER_SIZE 20 00015 00016 #define TIME_BITTIME 833 // us, 1200bps 00017 #define TIME_BITTIME1p2 417 // us, 1200bps 1/2 00018 #define TIME_BITTIME3p4 625 // us, 1200bps 3/4 00019 #define TIME_BETWEEN 10000 // us >22Te 00020 00021 00022 DALI::DALI (PinName tx, PinName rx) : _tx(tx), _rx(rx) { 00023 _rx.mode(PullUp); 00024 _rx.fall(this, &DALI::isr_rx); 00025 _rx.rise(this, &DALI::isr_rx); 00026 _tx = 0; 00027 00028 recv_buf = new CircBuffer<int>(BUFFER_SIZE); 00029 send_buf = new CircBuffer<int>(BUFFER_SIZE); 00030 00031 mode = 0; 00032 count = 0; 00033 timeflg = 0; 00034 busy = 0; 00035 } 00036 00037 int DALI::read (enum DALI_FRAME *frame, int *addr, int *value) { 00038 int dat; 00039 00040 if (recv_buf->dequeue(&dat)) { 00041 if (dat & (1<<16)) { 00042 *frame = BACKWARD; 00043 *value = dat & 0xff; 00044 } else { 00045 if (dat & (1<<15)) { 00046 // group 00047 if (dat & (1<<8)) { 00048 *frame = FORWARD_GROUP_IAP; 00049 } else { 00050 *frame = FORWARD_GROUP_DAP; 00051 } 00052 } else { 00053 // short 00054 if (dat & (1<<8)) { 00055 *frame = FORWARD_SHORT_IAP; 00056 } else { 00057 *frame = FORWARD_SHORT_DAP; 00058 } 00059 } 00060 *addr = (dat >> 9) & 0x3f; 00061 *value = dat & 0xff; 00062 } 00063 return 0; 00064 } 00065 return -1; 00066 } 00067 00068 int DALI::readable () { 00069 return ! recv_buf->isEmpty(); 00070 } 00071 00072 void DALI::isr_send () { 00073 00074 if (! busy) { 00075 if (mode) return; // recv working 00076 00077 _ticker.detach(); 00078 // next data 00079 int dat, bit; 00080 busy = 1; 00081 send_buf->dequeue(&dat); 00082 bit = (dat >> 20) & 0x0fff; 00083 send_bit = (1 << bit) << 2; 00084 send_data = dat & 0x0fffff; 00085 halfbit = 0; 00086 _ticker.attach_us(this, &DALI::isr_send, TIME_BITTIME1p2); 00087 } 00088 00089 if (send_bit & 3) { 00090 // stop bit 00091 _tx = 0; 00092 } else 00093 if ((halfbit == 0 && (send_data & send_bit)) || (halfbit == 1 && !(send_data & send_bit))) { 00094 // low 00095 _tx = 1; 00096 } else { 00097 // high 00098 _tx = 0; 00099 } 00100 00101 if (halfbit) { 00102 halfbit = 0; 00103 send_bit >>= 1; 00104 00105 if (send_bit == 0) { 00106 // end of data 00107 _ticker.detach(); 00108 busy = 0; 00109 if (! send_buf->isEmpty()) { 00110 // next data 00111 _ticker.attach_us(this, &DALI::isr_send, TIME_BETWEEN); 00112 } 00113 } 00114 } else { 00115 halfbit = 1; 00116 } 00117 } 00118 00119 int DALI::writable () { 00120 return ! send_buf->isFull(); 00121 } 00122 00123 int DALI::write (enum DALI_FRAME frame, int addr, int value) { 00124 int dat, bit; 00125 00126 switch (frame) { 00127 case FORWARD_SHORT_DAP: 00128 dat = (0<<15) | ((addr & 0x3f) << 9) | (0<<8) | (value & 0xff); 00129 bit = 16; 00130 break; 00131 00132 case FORWARD_SHORT_IAP: 00133 dat = (0<<15) | ((addr & 0x3f) << 9) | (1<<8) | (value & 0xff); 00134 bit = 16; 00135 break; 00136 00137 case FORWARD_GROUP_DAP: 00138 dat = (1<<15) | ((addr & 0x3f) << 9) | (0<<8) | (value & 0xff); 00139 bit = 16; 00140 break; 00141 00142 case FORWARD_GROUP_IAP: 00143 dat = (1<<15) | ((addr & 0x3f) << 9) | (1<<8) | (value & 0xff); 00144 bit = 16; 00145 break; 00146 00147 case BACKWARD: 00148 dat = (value & 0xff); 00149 bit = 8; 00150 break; 00151 00152 default: 00153 return -1; 00154 } 00155 00156 dat = ((1<<bit) | dat) << 2; // start bit 00157 dat |= bit << 20; 00158 send_buf->queue(dat); 00159 00160 if (! busy) { 00161 while (mode); // wait recv 00162 // begin data 00163 busy = 1; 00164 send_buf->dequeue(&dat); 00165 bit = (dat >> 20) & 0x0fff; 00166 send_bit = (1 << bit) << 2; 00167 send_data = dat & 0x0fffff; 00168 halfbit = 0; 00169 _ticker.attach_us(this, &DALI::isr_send, TIME_BITTIME1p2); 00170 } 00171 return 0; 00172 } 00173 00174 void DALI::isr_rx () { 00175 00176 if (timeflg || busy) return; 00177 00178 timeflg = 1; 00179 _timer.detach(); 00180 _timer.attach_us(this, &DALI::isr_timer, TIME_BITTIME3p4); 00181 00182 if (_rx.read() && mode == 0) { 00183 // start bit 00184 mode ++; 00185 recv_data = 0; 00186 recv_bit = 0x8000; 00187 } 00188 } 00189 00190 void DALI::isr_timer () { 00191 timeflg = 0; 00192 _timer.detach(); 00193 _timer.attach_us(this, &DALI::isr_timeout, TIME_BITTIME); 00194 00195 if (recv_bit) { 00196 // data bit 00197 if (_rx.read()) { 00198 // high 00199 recv_data |= recv_bit; 00200 } else { 00201 // low 00202 recv_data &= ~recv_bit; 00203 } 00204 recv_bit >>= 1; 00205 } else 00206 if (mode == 1) { 00207 if (_rx.read()) { 00208 // error 00209 mode = 0; 00210 } else { 00211 // stop bit 1 00212 mode ++; 00213 } 00214 } 00215 } 00216 00217 void DALI::isr_timeout () { 00218 timeflg = 0; 00219 _timer.detach(); 00220 00221 if (recv_bit) { 00222 // Backward frame (8bit) 00223 if (mode == 1 && _rx.read() == 0 && !(recv_data & (1<<7))) { 00224 // stop bit 2 00225 recv_data = (1<<16) | (recv_data >> 8); 00226 recv_buf->queue(recv_data); 00227 mode = 0; 00228 } else { 00229 mode = 0; 00230 } 00231 } else { 00232 // Forward frame (16bit) 00233 if (mode == 2 && _rx.read() == 0) { 00234 // stop bit 2 00235 recv_buf->queue(recv_data); 00236 mode = 0; 00237 } else { 00238 mode = 0; 00239 } 00240 } 00241 }
Generated on Wed Jul 20 2022 19:38:24 by 1.7.2