Library for TM1650 LED controller (32 LEDs max, 28 keys max)
Embed:
(wiki syntax)
Show/hide line numbers
TM1650.cpp
00001 /* mbed TM1650 Library, for TM1650 LED controller 00002 * Copyright (c) 2017, v01: WH, Initial version 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, inclumosig without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUmosiG BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 * THE SOFTWARE. 00021 */ 00022 #include "mbed.h" 00023 #include "TM1650.h" 00024 00025 /** Constructor for class for driving TM1650 LED controller with Serial bus interface device. 00026 * @brief Supports 4 digits @ 8 segments. Also supports upto 28 Keys. 00027 * 00028 * @param PinName dio Serial bus DIO pin 00029 * @param PinName clk Serial bus CLK pin 00030 */ 00031 TM1650::TM1650(PinName dio, PinName clk) : _dio(dio), _clk(clk) { 00032 00033 _init(); 00034 } 00035 00036 00037 /** Init the Serial interface and the controller 00038 * @param none 00039 * @return none 00040 */ 00041 void TM1650::_init(){ 00042 00043 //TM1650 uses a Serial bus that looks like I2C, but really is not. 00044 //It has Start and Stop conditions like I2C and an Ack pulse, but instead of slaveaddresses and a RW bit it just transmits commands and data. 00045 00046 //init Serial bus 00047 _dio.output(); 00048 // _dio.mode(PullUp); 00049 wait_us(1); 00050 00051 _dio=1; 00052 _clk=1; 00053 00054 //init controller 00055 _bright = TM1650_BRT_DEF; 00056 _segment = TM1650_DSP_8S; 00057 _display = TM1650_DSP_ON; 00058 _writeCmd(TM1650_DSP_CTRL_CMD, _bright | _segment | _display ); // Display control cmd, brightness, 7/8 segments, display on/off 00059 } 00060 00061 00062 /** Clear the screen and locate to 0 00063 */ 00064 void TM1650::cls() { 00065 00066 for (int cnt=0; cnt<TM1650_DISPLAY_MEM; cnt++) { 00067 _start(); 00068 _write(TM1650_DATA_WR_CMD | (cnt << 1)); // Set Address cmd (no auto incr supported) 00069 _write(0x00); // Write data 00070 _stop(); 00071 } 00072 00073 } 00074 00075 /** Set Brightness 00076 * 00077 * @param char brightness (3 significant bits, valid range 0..7 (1/16 .. 14/14 dutycycle) 00078 * @return none 00079 */ 00080 void TM1650::setBrightness(char brightness){ 00081 00082 _bright = brightness & TM1650_BRT_MSK; // mask invalid bits 00083 00084 _writeCmd(TM1650_DSP_CTRL_CMD, _bright | _segment | _display ); // Display control cmd, brightness, 7/8 segments, display on/off 00085 } 00086 00087 /** Set the Display mode On/off 00088 * 00089 * @param bool display mode 00090 */ 00091 void TM1650::setDisplay(bool on) { 00092 00093 if (on) { 00094 _display = TM1650_DSP_ON; 00095 } 00096 else { 00097 _display = TM1650_DSP_OFF; 00098 } 00099 00100 _writeCmd(TM1650_DSP_CTRL_CMD, _bright | _segment | _display ); // Display control cmd, brightness, 7/8 segments, display on/off 00101 } 00102 00103 /** Write databyte to TM1650 00104 * @param int address display memory location to write byte 00105 * @param char data byte written at given address 00106 * @return none 00107 */ 00108 void TM1650::writeData(char data, int address) { 00109 00110 _start(); 00111 00112 _write(TM1650_DATA_WR_CMD | ((address & TM1650_ADDR_MSK) << 1)); // Set Address cmd 00113 _write(data); // Write data 00114 00115 _stop(); 00116 } 00117 00118 /** Write Display datablock to TM1650 00119 * @param DisplayData_t data Array of TM1650_DISPLAY_MEM (=4) bytes for displaydata 00120 * @param length number bytes to write (valid range 0..(TM1650_MAX_NR_GRIDS * TM1650_BYTES_PER_GRID) (=4), when starting at address 0) 00121 * @param int address display memory location to write bytes (default = 0) 00122 * @return none 00123 */ 00124 void TM1650::writeData(DisplayData_t data, int length, int address) { 00125 00126 // sanity check 00127 address &= TM1650_ADDR_MSK; 00128 if (length < 0) {length = 0;} 00129 if ((length + address) > TM1650_DISPLAY_MEM) {length = (TM1650_DISPLAY_MEM - address);} 00130 00131 for (int idx=0; idx<length; idx++) { 00132 _start(); 00133 _write(TM1650_DATA_WR_CMD | ((address + idx) << 1)); // Set Address cmd (no auto incr supported) 00134 _write(data[address + idx]); // Write data 00135 _stop(); 00136 } 00137 } 00138 00139 /** Read keydata block from TM1650 00140 * @param *keydata Ptr to bytes for keydata 00141 * @return bool keypress True when at least one key was pressed 00142 */ 00143 bool TM1650::getKeys(KeyData_t *keydata) { 00144 00145 _start(); 00146 00147 // Enable Key Read mode 00148 _write(TM1650_KEY_RD_CMD); // Read Key cmd 00149 00150 // Read key 00151 *keydata = _read(); 00152 // printf("Key = 0x%02x\r\n", *keydata); // debug 00153 00154 _stop(); 00155 00156 // Check if valid key bits are set 00157 return ( (*keydata & TM1650_SW_MSK) == TM1650_SW_MSK ); 00158 } 00159 00160 00161 /** Generate Start condition for TM1650 00162 * @param none 00163 * @return none 00164 */ 00165 void TM1650::_start() { 00166 00167 _dio=0; 00168 wait_us(1); 00169 _clk=0; 00170 wait_us(1); 00171 } 00172 00173 /** Generate Stop condition for TM1650 00174 * @param none 00175 * @return none 00176 */ 00177 void TM1650::_stop() { 00178 00179 _dio=0; 00180 wait_us(1); 00181 _clk=1; 00182 wait_us(1); 00183 _dio=1; 00184 wait_us(1); 00185 } 00186 00187 /** Send byte to TM1650 00188 * @param int data 00189 * @return none 00190 */ 00191 void TM1650::_write(int data) { 00192 00193 for (int bit=7; bit >= 0; bit--) { 00194 //The TM1650 expects MSB first 00195 if (((data >> bit) & 0x01) == 0x01) { 00196 _dio=1; 00197 } 00198 else { 00199 _dio=0; 00200 } 00201 wait_us(1); 00202 _clk=1; 00203 wait_us(1); 00204 _clk=0; 00205 wait_us(1); 00206 } 00207 00208 _dio=1; 00209 00210 // Prepare DIO to read data 00211 _dio.input(); 00212 wait_us(3); 00213 00214 // dummy Ack 00215 _clk=1; 00216 wait_us(1); 00217 // _ack = _dio; 00218 _clk=0; 00219 wait_us(1); 00220 00221 // Return DIO to output mode 00222 _dio.output(); 00223 wait_us(3); 00224 00225 _dio=1; //idle 00226 } 00227 00228 /** Read byte from TM1650 00229 * @param none 00230 * @return read byte 00231 */ 00232 char TM1650::_read() { 00233 char keycode = 0; 00234 00235 // Prepare DIO to read data 00236 _dio.input(); 00237 wait_us(3); 00238 00239 for (int bit=0; bit<8; bit++) { 00240 00241 //The TM1650 sends bitpattern: D7..D0 00242 //Data is shifted out by the TM1650 on the falling edge of CLK 00243 //Observe sufficient delay to allow the Open Drain DIO to rise to H levels 00244 // Prepare to read next bit, MSB (ie D7) first. 00245 keycode = keycode << 1; 00246 00247 _clk=1; 00248 wait_us(1); 00249 00250 // Read next bit 00251 if (_dio) { keycode |= 0x01; } 00252 00253 _clk=0; 00254 wait_us(5); // Delay to allow for slow risetime 00255 } 00256 00257 // Return DIO to output mode 00258 _dio.output(); 00259 wait_us(3); 00260 00261 // dummy Ack 00262 _dio=0; //Ack 00263 wait_us(1); 00264 00265 _clk=1; 00266 wait_us(1); 00267 _clk=0; 00268 wait_us(1); 00269 00270 _dio=1; //idle 00271 00272 return keycode; 00273 } 00274 00275 /** Write command (and parameters) to TM1650 00276 * @param int cmd Command byte 00277 * @Param int data Parameters for command 00278 * @return none 00279 */ 00280 void TM1650::_writeCmd(int cmd, int data){ 00281 00282 _start(); 00283 00284 _write(cmd); 00285 _write(data); 00286 00287 _stop(); 00288 } 00289 00290 00291 #if (MEIBAI_TEST == 1) 00292 // Derived class for TM1650 used in MEIBAI display unit 00293 // 00294 00295 /** Constructor for class for driving TM1650 LED controller 00296 * 00297 * @brief Supports 4 Digits of 7 Segments + DP. 00298 * Also supports 3 keys. 00299 * Serial bus interface device. 00300 * 00301 * @param PinName dio Serial bus DIO pin 00302 * @param PinName sck Serial bus CLK pin 00303 */ 00304 TM1650_MEIBAI::TM1650_MEIBAI(PinName dio, PinName clk) : TM1650(dio, clk) { 00305 _column = 0; 00306 _columns = MEIBAI_NR_DIGITS; 00307 } 00308 00309 #if(0) 00310 #if DOXYGEN_ONLY 00311 /** Write a character to the Display 00312 * 00313 * @param c The character to write to the display 00314 * @return c 00315 */ 00316 int putc(int c); 00317 00318 /** Write a formatted string to the Display 00319 * 00320 * @param format A printf-style format string, followed by the 00321 * variables to use in formatting the string. 00322 */ 00323 int printf(const char* format, ...); 00324 #endif 00325 #endif 00326 00327 /** Locate cursor to a screen column 00328 * 00329 * @param column The horizontal position from the left, indexed from 0 00330 * @return none 00331 */ 00332 void TM1650_MEIBAI::locate(int column) { 00333 //sanity check 00334 if (column < 0) {column = 0;} 00335 if (column > (_columns - 1)) {column = _columns - 1;} 00336 00337 _column = column; 00338 } 00339 00340 00341 /** Number of screen columns 00342 * 00343 * @param none 00344 * @return columns 00345 */ 00346 int TM1650_MEIBAI::columns() { 00347 return _columns; 00348 } 00349 00350 00351 /** Clear the screen and locate to 0 00352 * 00353 * @param bool clrAll Clear Icons also (default = false) 00354 * @return none 00355 */ 00356 void TM1650_MEIBAI::cls(bool clrAll) { 00357 00358 if (clrAll) { 00359 //clear local buffer (inclumosig Icons) 00360 for (int idx=0; idx < MEIBAI_NR_GRIDS; idx++) { 00361 _displaybuffer[idx] = 0x00; 00362 } 00363 } 00364 else { 00365 //clear local buffer (preserving Icons) 00366 for (int idx=0; idx < MEIBAI_NR_GRIDS; idx++) { 00367 _displaybuffer[idx] = _displaybuffer[idx] & MASK_ICON_GRID[idx]; 00368 } 00369 } 00370 00371 writeData(_displaybuffer, (MEIBAI_NR_GRIDS * TM1650_BYTES_PER_GRID), 0); 00372 00373 _column = 0; 00374 } 00375 00376 /** Set Icon 00377 * 00378 * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 16 LSBs 00379 * @return none 00380 */ 00381 void TM1650_MEIBAI::setIcon(Icon icon) { 00382 int addr, icn; 00383 00384 icn = icon & 0xFFFF; 00385 addr = (icon >> 24) & 0xFF; 00386 addr = (addr - 1); 00387 00388 //Save char...and set bits for icon to write 00389 _displaybuffer[addr] = _displaybuffer[addr] | LO(icn); 00390 // writeData(_displaybuffer, (MEIBAI_NR_GRIDS * TM1650_BYTES_PER_GRID), 0); 00391 writeData(_displaybuffer, TM1650_BYTES_PER_GRID, addr); 00392 } 00393 00394 /** Clr Icon 00395 * 00396 * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 16 LSBs 00397 * @return none 00398 */ 00399 void TM1650_MEIBAI::clrIcon(Icon icon) { 00400 int addr, icn; 00401 00402 icn = icon & 0xFFFF; 00403 addr = (icon >> 24) & 0xFF; 00404 addr = (addr - 1); 00405 00406 //Save char...and clr bits for icon to write 00407 _displaybuffer[addr] = _displaybuffer[addr] & ~LO(icn); 00408 // writeData(_displaybuffer, (MEIBAI_NR_GRIDS * TM1650_BYTES_PER_GRID), 0); 00409 writeData(_displaybuffer, TM1650_BYTES_PER_GRID, addr); 00410 } 00411 00412 00413 /** Set User Defined Characters (UDC) 00414 * 00415 * @param unsigned char udc_idx The Index of the UDC (0..7) 00416 * @param int udc_data The bitpattern for the UDC (8 bits) 00417 * @return none 00418 */ 00419 void TM1650_MEIBAI::setUDC(unsigned char udc_idx, int udc_data) { 00420 00421 //Sanity check 00422 if (udc_idx > (MEIBAI_NR_UDC-1)) { 00423 return; 00424 } 00425 // Mask out Icon bits? 00426 00427 _UDC_7S[udc_idx] = LO(udc_data); 00428 } 00429 00430 00431 /** Write a single character (Stream implementation) 00432 * 00433 * @param c The character to write to the display 00434 * @return c 00435 */ 00436 int TM1650_MEIBAI::_putc(int value) { 00437 //The MEIBAI mapping between Digit positions (Left to Right) and Grids is: 00438 // GR1 GR2 GR3 GR4 00439 //The memory addresses or column numbers are: 00440 // 0 1 2 3 00441 00442 int addr; 00443 bool validChar = false; 00444 char pattern = 0x00; 00445 00446 if ((value == '\n') || (value == '\r')) { 00447 //No character to write 00448 validChar = false; 00449 00450 //Update Cursor 00451 _column = 0; 00452 } 00453 else if ((value == '.') || (value == ',')) { 00454 //No character to write 00455 validChar = false; 00456 pattern = S7_DP; // placeholder for all DPs 00457 00458 // Check to see that DP can be shown for current column 00459 if (_column > 0) { 00460 //Translate between _column and displaybuffer entries 00461 //Add DP to bitpattern of digit left of current column. 00462 addr = (_column - 1); 00463 00464 //Save icons...and set bits for decimal point to write 00465 _displaybuffer[addr] = _displaybuffer[addr] | pattern; 00466 // writeData(_displaybuffer, (MEIBAI_NR_GRIDS * TM1650_BYTES_PER_GRID)); 00467 writeData(_displaybuffer, TM1650_BYTES_PER_GRID, addr); 00468 00469 //No Cursor Update 00470 } 00471 } 00472 else if ((value >= 0) && (value < MEIBAI_NR_UDC)) { 00473 //Character to write 00474 validChar = true; 00475 pattern = _UDC_7S[value]; 00476 } 00477 00478 #if (SHOW_ASCII == 1) 00479 //display all ASCII characters 00480 else if ((value >= FONT_7S_START) && (value <= FONT_7S_END)) { 00481 //Character to write 00482 validChar = true; 00483 pattern = FONT_7S[value - FONT_7S_START]; 00484 } // else 00485 #else 00486 //display only digits and hex characters 00487 else if (value == '-') { 00488 //Character to write 00489 validChar = true; 00490 pattern = C7_MIN; 00491 } 00492 else if ((value >= (int)'0') && (value <= (int) '9')) { 00493 //Character to write 00494 validChar = true; 00495 pattern = FONT_7S[value - (int) '0']; 00496 } 00497 else if ((value >= (int) 'A') && (value <= (int) 'F')) { 00498 //Character to write 00499 validChar = true; 00500 pattern = FONT_7S[10 + value - (int) 'A']; 00501 } 00502 else if ((value >= (int) 'a') && (value <= (int) 'f')) { 00503 //Character to write 00504 validChar = true; 00505 pattern = FONT_7S[10 + value - (int) 'a']; 00506 } //else 00507 #endif 00508 00509 if (validChar) { 00510 //Character to write 00511 00512 //Translate between _column and displaybuffer entries 00513 addr = _column; 00514 00515 //Save icons...and set bits for character to write 00516 _displaybuffer[addr] = (_displaybuffer[addr] & MASK_ICON_GRID[_column]) | pattern; 00517 00518 // writeData(_displaybuffer, (MEIBAI_NR_GRIDS * TM1650_BYTES_PER_GRID)); 00519 writeData(_displaybuffer, TM1650_BYTES_PER_GRID, addr); 00520 00521 //Update Cursor 00522 _column++; 00523 if (_column > (MEIBAI_NR_DIGITS - 1)) { 00524 _column = 0; 00525 } 00526 00527 } // if validChar 00528 00529 return value; 00530 } 00531 00532 00533 /** Get a single character (Stream implementation) 00534 * 00535 * @param none 00536 * @return -1 00537 */ 00538 int TM1650_MEIBAI::_getc() { 00539 return -1; 00540 } 00541 00542 #endif
Generated on Wed Jul 13 2022 19:08:39 by 1.7.2