Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
TM1650 LED controller (32 LEDs max), Keyboard scan (28 keys max).