Library for Princeton PT6961 LED driver. Supports 6 digits @ 12 segments or 7 digits @ 11 segments. Also supports keyboard scanning of upto 30 keys. SPI interface.

Dependents:   mbed_PT6961

This LED driver is found in frontpanel controllers of consumer electronics such as DVD players. The added features such as the matrix keyboard scanning are useful in these applications.

Additional information is available on the component page here

Committer:
wim
Date:
Sun Sep 20 13:28:46 2015 +0000
Revision:
0:feebe8eca523
Child:
1:eb4758bba68a
First Release version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wim 0:feebe8eca523 1 /* mbed PT6961 Library, for Princeton PT6961 LED controller
wim 0:feebe8eca523 2 * Copyright (c) 2015, v01: WH, Initial version
wim 0:feebe8eca523 3 *
wim 0:feebe8eca523 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
wim 0:feebe8eca523 5 * of this software and associated documentation files (the "Software"), to deal
wim 0:feebe8eca523 6 * in the Software without restriction, including without limitation the rights
wim 0:feebe8eca523 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
wim 0:feebe8eca523 8 * copies of the Software, and to permit persons to whom the Software is
wim 0:feebe8eca523 9 * furnished to do so, subject to the following conditions:
wim 0:feebe8eca523 10 *
wim 0:feebe8eca523 11 * The above copyright notice and this permission notice shall be included in
wim 0:feebe8eca523 12 * all copies or substantial portions of the Software.
wim 0:feebe8eca523 13 *
wim 0:feebe8eca523 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
wim 0:feebe8eca523 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
wim 0:feebe8eca523 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
wim 0:feebe8eca523 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
wim 0:feebe8eca523 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
wim 0:feebe8eca523 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
wim 0:feebe8eca523 20 * THE SOFTWARE.
wim 0:feebe8eca523 21 */
wim 0:feebe8eca523 22 #include "mbed.h"
wim 0:feebe8eca523 23 #include "PT6961.h"
wim 0:feebe8eca523 24
wim 0:feebe8eca523 25 /** Constructor for class for driving Princeton PT6961 LED controller with SPI bus interface device.
wim 0:feebe8eca523 26 * @brief Supports 6 Digits or 12 Segments or 7 Digits of 11 Segments. Also supports a scanned keyboard of upto 30 keys.
wim 0:feebe8eca523 27 *
wim 0:feebe8eca523 28 * @param PinName mosi, miso, sclk, cs SPI bus pins
wim 0:feebe8eca523 29 * @param Mode selects either 6 Digits of 12 Segments or 7 Digits of 11 Segments (default)
wim 0:feebe8eca523 30 */
wim 0:feebe8eca523 31 PT6961::PT6961(PinName mosi, PinName miso, PinName sclk, PinName cs, Mode mode) : _spi(mosi,miso,sclk), _cs(cs), _mode(mode) {
wim 0:feebe8eca523 32
wim 0:feebe8eca523 33 _init();
wim 0:feebe8eca523 34 }
wim 0:feebe8eca523 35
wim 0:feebe8eca523 36 /** Init the SPI interface and the controller
wim 0:feebe8eca523 37 * @param none
wim 0:feebe8eca523 38 * @return none
wim 0:feebe8eca523 39 */
wim 0:feebe8eca523 40 void PT6961::_init(){
wim 0:feebe8eca523 41
wim 0:feebe8eca523 42 //init SPI
wim 0:feebe8eca523 43 _cs=1;
wim 0:feebe8eca523 44 _spi.format(8,3); //PT6961 uses mode 3 (Clock High on Idle, Data latched on second (=rising) edge)
wim 0:feebe8eca523 45 _spi.frequency(500000);
wim 0:feebe8eca523 46
wim 0:feebe8eca523 47 //init controller
wim 0:feebe8eca523 48 _writeCmd(PT6961_MODE_SET_CMD, _mode); // Mode set command
wim 0:feebe8eca523 49
wim 0:feebe8eca523 50 _display = PT6961_DSP_ON;
wim 0:feebe8eca523 51 _bright = PT6961_BRT_DEF;
wim 0:feebe8eca523 52 _writeCmd(PT6961_DSP_CTRL_CMD, _display | _bright ); // Display control cmd, display on/off, brightness
wim 0:feebe8eca523 53
wim 0:feebe8eca523 54 _writeCmd(PT6961_DATA_SET_CMD, PT6961_DATA_WR | PT6961_ADDR_INC | PT6961_MODE_NORM); // Data set cmd, normal mode, auto incr, write data
wim 0:feebe8eca523 55 }
wim 0:feebe8eca523 56
wim 0:feebe8eca523 57
wim 0:feebe8eca523 58 /** Clear the screen and locate to 0
wim 0:feebe8eca523 59 */
wim 0:feebe8eca523 60 void PT6961::cls() {
wim 0:feebe8eca523 61
wim 0:feebe8eca523 62 _cs=0;
wim 0:feebe8eca523 63 wait_us(1);
wim 0:feebe8eca523 64 _spi.write(_flip(PT6961_ADDR_SET_CMD | 0x00)); // Address set cmd, 0
wim 0:feebe8eca523 65
wim 0:feebe8eca523 66 for (int cnt=0; cnt<PT6961_DISPLAY_MEM; cnt++) {
wim 0:feebe8eca523 67 _spi.write(0x00); // data
wim 0:feebe8eca523 68 }
wim 0:feebe8eca523 69
wim 0:feebe8eca523 70 wait_us(1);
wim 0:feebe8eca523 71 _cs=1;
wim 0:feebe8eca523 72 }
wim 0:feebe8eca523 73
wim 0:feebe8eca523 74 /** Set Brightness
wim 0:feebe8eca523 75 *
wim 0:feebe8eca523 76 * @param char brightness (3 significant bits, valid range 0..7 (1/16 .. 14/14 dutycycle)
wim 0:feebe8eca523 77 * @return none
wim 0:feebe8eca523 78 */
wim 0:feebe8eca523 79 void PT6961::setBrightness(char brightness){
wim 0:feebe8eca523 80
wim 0:feebe8eca523 81 _bright = brightness & PT6961_BRT_MSK; // mask invalid bits
wim 0:feebe8eca523 82
wim 0:feebe8eca523 83 _writeCmd(PT6961_DSP_CTRL_CMD, _display | _bright ); // Display control cmd, display on/off, brightness
wim 0:feebe8eca523 84 }
wim 0:feebe8eca523 85
wim 0:feebe8eca523 86 /** Set the Display mode On/off
wim 0:feebe8eca523 87 *
wim 0:feebe8eca523 88 * @param bool display mode
wim 0:feebe8eca523 89 */
wim 0:feebe8eca523 90 void PT6961::setDisplay(bool on) {
wim 0:feebe8eca523 91
wim 0:feebe8eca523 92 if (on) {
wim 0:feebe8eca523 93 _display = PT6961_DSP_ON;
wim 0:feebe8eca523 94 }
wim 0:feebe8eca523 95 else {
wim 0:feebe8eca523 96 _display = PT6961_DSP_OFF;
wim 0:feebe8eca523 97 }
wim 0:feebe8eca523 98
wim 0:feebe8eca523 99 _writeCmd(PT6961_DSP_CTRL_CMD, _display | _bright ); // Display control cmd, display on/off, brightness
wim 0:feebe8eca523 100 }
wim 0:feebe8eca523 101
wim 0:feebe8eca523 102 /** Write databyte to PT6961
wim 0:feebe8eca523 103 * @param int address display memory location to write byte
wim 0:feebe8eca523 104 * @param char data byte written at given address
wim 0:feebe8eca523 105 * @return none
wim 0:feebe8eca523 106 */
wim 0:feebe8eca523 107 void PT6961::writeData(int address, char data) {
wim 0:feebe8eca523 108 _cs=0;
wim 0:feebe8eca523 109 wait_us(1);
wim 0:feebe8eca523 110 _spi.write(_flip(PT6961_ADDR_SET_CMD | (address & PT6961_ADDR_MSK))); // Set Address cmd
wim 0:feebe8eca523 111
wim 0:feebe8eca523 112 _spi.write(_flip(data)); // data
wim 0:feebe8eca523 113
wim 0:feebe8eca523 114 wait_us(1);
wim 0:feebe8eca523 115 _cs=1;
wim 0:feebe8eca523 116 }
wim 0:feebe8eca523 117
wim 0:feebe8eca523 118 /** Write Display datablock to PT6961
wim 0:feebe8eca523 119 * @param DisplayData_t data Array of PT6961_DISPLAY_MEM (=14) bytes for displaydata (starting at address 0)
wim 0:feebe8eca523 120 * @param length number bytes to write (valide range 0..PT6961_DISPLAY_MEM (=14), starting at address 0)
wim 0:feebe8eca523 121 * @return none
wim 0:feebe8eca523 122 */
wim 0:feebe8eca523 123 void PT6961::writeData(DisplayData_t data, int length) {
wim 0:feebe8eca523 124 _cs=0;
wim 0:feebe8eca523 125 wait_us(1);
wim 0:feebe8eca523 126 _spi.write(_flip(PT6961_ADDR_SET_CMD | 0x00)); // Set Address at 0
wim 0:feebe8eca523 127
wim 0:feebe8eca523 128 // sanity check
wim 0:feebe8eca523 129 if (length < 0) {length = 0;}
wim 0:feebe8eca523 130 if (length > PT6961_DISPLAY_MEM) {length = PT6961_DISPLAY_MEM;}
wim 0:feebe8eca523 131
wim 0:feebe8eca523 132 // for (int idx=0; idx<PT6961_DISPLAY_MEM; idx++) {
wim 0:feebe8eca523 133 for (int idx=0; idx<length; idx++) {
wim 0:feebe8eca523 134 _spi.write(_flip(data[idx])); // data
wim 0:feebe8eca523 135 }
wim 0:feebe8eca523 136
wim 0:feebe8eca523 137 wait_us(1);
wim 0:feebe8eca523 138 _cs=1;
wim 0:feebe8eca523 139 }
wim 0:feebe8eca523 140
wim 0:feebe8eca523 141
wim 0:feebe8eca523 142 /** Read keydata block from PT6961
wim 0:feebe8eca523 143 * @param *keydata Ptr to Array of PT6961_KEY_MEM (=5) bytes for keydata
wim 0:feebe8eca523 144 * @return bool keypress True when at least one key was pressed
wim 0:feebe8eca523 145 *
wim 0:feebe8eca523 146 * Note: Due to the hardware configuration the PT6961 key matrix scanner will detect multiple keys pressed at same time,
wim 0:feebe8eca523 147 * but this may also result in some spurious keys being set in keypress data array.
wim 0:feebe8eca523 148 * It may be best to ignore all keys in those situations. That option is implemented in this method depending on #define setting.
wim 0:feebe8eca523 149 */
wim 0:feebe8eca523 150 bool PT6961::getKeys(KeyData_t *keydata) {
wim 0:feebe8eca523 151 int keypress = 0;
wim 0:feebe8eca523 152 char data;
wim 0:feebe8eca523 153
wim 0:feebe8eca523 154 // Read keys
wim 0:feebe8eca523 155 _cs=0;
wim 0:feebe8eca523 156 wait_us(1);
wim 0:feebe8eca523 157
wim 0:feebe8eca523 158 // Enable Key Read mode
wim 0:feebe8eca523 159 _spi.write(_flip(PT6961_DATA_SET_CMD | PT6961_KEY_RD | PT6961_ADDR_INC | PT6961_MODE_NORM)); // Data set cmd, normal mode, auto incr, read data
wim 0:feebe8eca523 160
wim 0:feebe8eca523 161 for (int idx=0; idx < PT6961_KEY_MEM; idx++) {
wim 0:feebe8eca523 162 data = _flip(_spi.write(0xFF)); // read keys and correct bitorder
wim 0:feebe8eca523 163
wim 0:feebe8eca523 164 if (data != 0) { // Check for any pressed key
wim 0:feebe8eca523 165 for (int bit=0; bit < PT6961_KEY_BITS; bit++) {
wim 0:feebe8eca523 166 if (data & (1 << bit)) {keypress++;} // Test all significant bits
wim 0:feebe8eca523 167 }
wim 0:feebe8eca523 168 }
wim 0:feebe8eca523 169
wim 0:feebe8eca523 170 (*keydata)[idx] = data; // Store keydata after correcting bitorder
wim 0:feebe8eca523 171 }
wim 0:feebe8eca523 172
wim 0:feebe8eca523 173 wait_us(1);
wim 0:feebe8eca523 174 _cs=1;
wim 0:feebe8eca523 175
wim 0:feebe8eca523 176 // Restore Data Write mode
wim 0:feebe8eca523 177 _writeCmd(PT6961_DATA_SET_CMD, PT6961_DATA_WR | PT6961_ADDR_INC | PT6961_MODE_NORM); // Data set cmd, normal mode, auto incr, write data
wim 0:feebe8eca523 178
wim 0:feebe8eca523 179 #if(1)
wim 0:feebe8eca523 180 // Dismiss multiple keypresses at same time
wim 0:feebe8eca523 181 return (keypress == 1);
wim 0:feebe8eca523 182 #else
wim 0:feebe8eca523 183 // Allow multiple keypress and accept possible spurious keys
wim 0:feebe8eca523 184 return (keypress > 0);
wim 0:feebe8eca523 185 #endif
wim 0:feebe8eca523 186 }
wim 0:feebe8eca523 187
wim 0:feebe8eca523 188
wim 0:feebe8eca523 189 /** Helper to reverse all command or databits. The PT6961 expects LSB first, whereas SPI is MSB first
wim 0:feebe8eca523 190 * @param char data
wim 0:feebe8eca523 191 * @return bitreversed data
wim 0:feebe8eca523 192 */
wim 0:feebe8eca523 193 char PT6961::_flip(char data) {
wim 0:feebe8eca523 194 char value=0;
wim 0:feebe8eca523 195
wim 0:feebe8eca523 196 if (data & 0x01) {value |= 0x80;} ;
wim 0:feebe8eca523 197 if (data & 0x02) {value |= 0x40;} ;
wim 0:feebe8eca523 198 if (data & 0x04) {value |= 0x20;} ;
wim 0:feebe8eca523 199 if (data & 0x08) {value |= 0x10;} ;
wim 0:feebe8eca523 200 if (data & 0x10) {value |= 0x08;} ;
wim 0:feebe8eca523 201 if (data & 0x20) {value |= 0x04;} ;
wim 0:feebe8eca523 202 if (data & 0x40) {value |= 0x02;} ;
wim 0:feebe8eca523 203 if (data & 0x80) {value |= 0x01;} ;
wim 0:feebe8eca523 204 return value;
wim 0:feebe8eca523 205 }
wim 0:feebe8eca523 206
wim 0:feebe8eca523 207
wim 0:feebe8eca523 208 /** Write command and parameter to PT6961
wim 0:feebe8eca523 209 * @param int cmd Command byte
wim 0:feebe8eca523 210 * &Param int data Parameters for command
wim 0:feebe8eca523 211 * @return none
wim 0:feebe8eca523 212 */
wim 0:feebe8eca523 213 void PT6961::_writeCmd(int cmd, int data){
wim 0:feebe8eca523 214
wim 0:feebe8eca523 215 _cs=0;
wim 0:feebe8eca523 216 wait_us(1);
wim 0:feebe8eca523 217 // _spi.write(_flip( (cmd & 0xF0) | (data & 0x0F)));
wim 0:feebe8eca523 218 _spi.write(_flip( (cmd & PT6961_CMD_MSK) | (data & ~PT6961_CMD_MSK)));
wim 0:feebe8eca523 219
wim 0:feebe8eca523 220 wait_us(1);
wim 0:feebe8eca523 221 _cs=1;
wim 0:feebe8eca523 222 }
wim 0:feebe8eca523 223
wim 0:feebe8eca523 224