Bird Techstep / MAX72XX

Fork of MAX72XX by Bird Techstep

Committer:
techstep
Date:
Mon Aug 04 11:11:57 2014 +0000
Revision:
0:8bdc990b1b57
Child:
1:dfa1f4cac4c9
MAX7219/MAX7221; Soft SPI Library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
techstep 0:8bdc990b1b57 1 /*****************************************************************************
techstep 0:8bdc990b1b57 2 * Type : C++
techstep 0:8bdc990b1b57 3 * File : MAX72XX.cpp
techstep 0:8bdc990b1b57 4 * Dec. : MAX7219 & MAX7221 Software SPI library
techstep 0:8bdc990b1b57 5 * Copyright (c) 2013-2014, Bird Techstep, tbird_th@hotmail.com
techstep 0:8bdc990b1b57 6 *
techstep 0:8bdc990b1b57 7 * Permission is hereby granted, free of charge, to any person obtaining a copy
techstep 0:8bdc990b1b57 8 * of this software and associated documentation files (the "Software"), to deal
techstep 0:8bdc990b1b57 9 * in the Software without restriction, including without limitation the rights
techstep 0:8bdc990b1b57 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
techstep 0:8bdc990b1b57 11 * copies of the Software, and to permit persons to whom the Software is
techstep 0:8bdc990b1b57 12 * furnished to do so, subject to the following conditions:
techstep 0:8bdc990b1b57 13 *
techstep 0:8bdc990b1b57 14 * The above copyright notice and this permission notice shall be included in
techstep 0:8bdc990b1b57 15 * all copies or substantial portions of the Software.
techstep 0:8bdc990b1b57 16 *
techstep 0:8bdc990b1b57 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
techstep 0:8bdc990b1b57 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
techstep 0:8bdc990b1b57 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
techstep 0:8bdc990b1b57 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
techstep 0:8bdc990b1b57 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
techstep 0:8bdc990b1b57 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
techstep 0:8bdc990b1b57 23 * THE SOFTWARE.
techstep 0:8bdc990b1b57 24 *****************************************************************************/
techstep 0:8bdc990b1b57 25 #include "mbed.h"
techstep 0:8bdc990b1b57 26 #include "MAX72XX.h"
techstep 0:8bdc990b1b57 27
techstep 0:8bdc990b1b57 28 #define LOW 0
techstep 0:8bdc990b1b57 29 #define HIGH 1
techstep 0:8bdc990b1b57 30
techstep 0:8bdc990b1b57 31 //The opcodes for the MAX7221 and MAX7219
techstep 0:8bdc990b1b57 32 #define OP_NOOP 0x00
techstep 0:8bdc990b1b57 33
techstep 0:8bdc990b1b57 34 #define OP_DIGIT0 0x01
techstep 0:8bdc990b1b57 35 #define OP_DIGIT1 0x02
techstep 0:8bdc990b1b57 36 #define OP_DIGIT2 0x03
techstep 0:8bdc990b1b57 37 #define OP_DIGIT3 0x04
techstep 0:8bdc990b1b57 38 #define OP_DIGIT4 0x05
techstep 0:8bdc990b1b57 39 #define OP_DIGIT5 0x06
techstep 0:8bdc990b1b57 40 #define OP_DIGIT6 0x07
techstep 0:8bdc990b1b57 41 #define OP_DIGIT7 0x08
techstep 0:8bdc990b1b57 42
techstep 0:8bdc990b1b57 43 #define OP_DECODEMODE 0x09 // 0x00 = No decode for digits 7–0
techstep 0:8bdc990b1b57 44 // 0x01 = Code B decode for digit 0, No decode for digits 7–1
techstep 0:8bdc990b1b57 45 // 0x0F = Code B decode for digits 3–0, No decode for digits 7–4
techstep 0:8bdc990b1b57 46 // 0xFF = Code B decode for digits 7–0
techstep 0:8bdc990b1b57 47 #define OP_INTENSITY 0x0A // 1/32..31/32 [0..15]
techstep 0:8bdc990b1b57 48 #define OP_SCANLIMIT 0x0B // 0x00 = Display digit 0
techstep 0:8bdc990b1b57 49 // 0x01 = Display digits 0 1
techstep 0:8bdc990b1b57 50 // 0x02 = Display digits 0 1 2
techstep 0:8bdc990b1b57 51 // 0x03 = Display digits 0 1 2 3
techstep 0:8bdc990b1b57 52 // 0x04 = Display digits 0 1 2 3 4
techstep 0:8bdc990b1b57 53 // 0x05 = Display digits 0 1 2 3 4 5
techstep 0:8bdc990b1b57 54 // 0x06 = Display digits 0 1 2 3 4 5 6
techstep 0:8bdc990b1b57 55 // 0x07 = Display digits 0 1 2 3 4 5 6 7
techstep 0:8bdc990b1b57 56 #define OP_SHUTDOWN 0x0C // 0x00 = Shutdown Mode
techstep 0:8bdc990b1b57 57 // 0x01 = Normal Operation
techstep 0:8bdc990b1b57 58 #define OP_DISPLAYTEST 0x0F // 0x00 = Normal Operation
techstep 0:8bdc990b1b57 59 // 0x01 = Display Test Mode
techstep 0:8bdc990b1b57 60
techstep 0:8bdc990b1b57 61
techstep 0:8bdc990b1b57 62 MAX72XX::MAX72XX(PinName mosi_pin, PinName miso_pin, PinName sclk_pin, PinName cs_pin, int numDevices) :cs(cs_pin) {
techstep 0:8bdc990b1b57 63 mosi = new DigitalOut(mosi_pin);
techstep 0:8bdc990b1b57 64 miso = new DigitalIn(miso_pin);
techstep 0:8bdc990b1b57 65 sclk = new DigitalOut(sclk_pin);
techstep 0:8bdc990b1b57 66 format(8);
techstep 0:8bdc990b1b57 67 frequency();
techstep 0:8bdc990b1b57 68
techstep 0:8bdc990b1b57 69 if(numDevices<=0 || numDevices>8 )
techstep 0:8bdc990b1b57 70 numDevices=8;
techstep 0:8bdc990b1b57 71 maxDevices=numDevices;
techstep 0:8bdc990b1b57 72 cs = 1;
techstep 0:8bdc990b1b57 73 for(int i=0;i<64;i++)
techstep 0:8bdc990b1b57 74 status[i] = 0x00;
techstep 0:8bdc990b1b57 75 for(int i=0;i<maxDevices;i++) {
techstep 0:8bdc990b1b57 76 spiTransfer(i,OP_DISPLAYTEST,0);
techstep 0:8bdc990b1b57 77 //scanlimit is set to max on startup
techstep 0:8bdc990b1b57 78 setScanLimit(i,7);
techstep 0:8bdc990b1b57 79 //decode is done in source
techstep 0:8bdc990b1b57 80 spiTransfer(i,OP_DECODEMODE,0);
techstep 0:8bdc990b1b57 81 clearDisplay(i);
techstep 0:8bdc990b1b57 82 //we go into shutdown-mode on startup
techstep 0:8bdc990b1b57 83 shutdown(i,true);
techstep 0:8bdc990b1b57 84 }
techstep 0:8bdc990b1b57 85 }
techstep 0:8bdc990b1b57 86
techstep 0:8bdc990b1b57 87 MAX72XX::~MAX72XX()
techstep 0:8bdc990b1b57 88 {
techstep 0:8bdc990b1b57 89 delete mosi;
techstep 0:8bdc990b1b57 90 delete miso;
techstep 0:8bdc990b1b57 91 delete sclk;
techstep 0:8bdc990b1b57 92 }
techstep 0:8bdc990b1b57 93
techstep 0:8bdc990b1b57 94 void MAX72XX::frequency(int hz)
techstep 0:8bdc990b1b57 95 {
techstep 0:8bdc990b1b57 96 this->freq = hz;
techstep 0:8bdc990b1b57 97 }
techstep 0:8bdc990b1b57 98
techstep 0:8bdc990b1b57 99 void MAX72XX::format(int bits, int mode)
techstep 0:8bdc990b1b57 100 {
techstep 0:8bdc990b1b57 101 this->bits = bits;
techstep 0:8bdc990b1b57 102 this->mode = mode;
techstep 0:8bdc990b1b57 103 polarity = (mode >> 1) & 1;
techstep 0:8bdc990b1b57 104 phase = mode & 1;
techstep 0:8bdc990b1b57 105 sclk->write(polarity);
techstep 0:8bdc990b1b57 106 }
techstep 0:8bdc990b1b57 107
techstep 0:8bdc990b1b57 108 int MAX72XX::write(int value)
techstep 0:8bdc990b1b57 109 {
techstep 0:8bdc990b1b57 110 int read = 0;
techstep 0:8bdc990b1b57 111 for (int bit = bits-1; bit >= 0; --bit)
techstep 0:8bdc990b1b57 112 {
techstep 0:8bdc990b1b57 113 mosi->write(((value >> bit) & 0x01) != 0);
techstep 0:8bdc990b1b57 114
techstep 0:8bdc990b1b57 115 if (phase == 0)
techstep 0:8bdc990b1b57 116 {
techstep 0:8bdc990b1b57 117 if (miso->read())
techstep 0:8bdc990b1b57 118 read |= (1 << bit);
techstep 0:8bdc990b1b57 119 }
techstep 0:8bdc990b1b57 120
techstep 0:8bdc990b1b57 121 sclk->write(!polarity);
techstep 0:8bdc990b1b57 122
techstep 0:8bdc990b1b57 123 wait(1.0/freq/2);
techstep 0:8bdc990b1b57 124
techstep 0:8bdc990b1b57 125 if (phase == 1)
techstep 0:8bdc990b1b57 126 {
techstep 0:8bdc990b1b57 127 if (miso->read())
techstep 0:8bdc990b1b57 128 read |= (1 << bit);
techstep 0:8bdc990b1b57 129 }
techstep 0:8bdc990b1b57 130
techstep 0:8bdc990b1b57 131 sclk->write(polarity);
techstep 0:8bdc990b1b57 132
techstep 0:8bdc990b1b57 133 wait(1.0/freq/2);
techstep 0:8bdc990b1b57 134 }
techstep 0:8bdc990b1b57 135 return read;
techstep 0:8bdc990b1b57 136 }
techstep 0:8bdc990b1b57 137
techstep 0:8bdc990b1b57 138 void MAX72XX::decodeMode(int addr, uint8_t mode) {
techstep 0:8bdc990b1b57 139 if(addr<0 || addr>=maxDevices)
techstep 0:8bdc990b1b57 140 return;
techstep 0:8bdc990b1b57 141 spiTransfer(addr, OP_DECODEMODE, mode);
techstep 0:8bdc990b1b57 142 }
techstep 0:8bdc990b1b57 143
techstep 0:8bdc990b1b57 144 void MAX72XX::displayTest(int addr, bool status) {
techstep 0:8bdc990b1b57 145 if(addr<0 || addr>=maxDevices)
techstep 0:8bdc990b1b57 146 return;
techstep 0:8bdc990b1b57 147 if(status)
techstep 0:8bdc990b1b57 148 spiTransfer(addr, OP_DISPLAYTEST,1);
techstep 0:8bdc990b1b57 149 else
techstep 0:8bdc990b1b57 150 spiTransfer(addr, OP_DISPLAYTEST,0);
techstep 0:8bdc990b1b57 151 }
techstep 0:8bdc990b1b57 152
techstep 0:8bdc990b1b57 153 void MAX72XX::shutdown(int addr, bool status) {
techstep 0:8bdc990b1b57 154 if(addr<0 || addr>=maxDevices)
techstep 0:8bdc990b1b57 155 return;
techstep 0:8bdc990b1b57 156 if(status)
techstep 0:8bdc990b1b57 157 spiTransfer(addr, OP_SHUTDOWN,0);
techstep 0:8bdc990b1b57 158 else
techstep 0:8bdc990b1b57 159 spiTransfer(addr, OP_SHUTDOWN,1);
techstep 0:8bdc990b1b57 160 }
techstep 0:8bdc990b1b57 161
techstep 0:8bdc990b1b57 162 void MAX72XX::setScanLimit(int addr, int limit) {
techstep 0:8bdc990b1b57 163 if(addr<0 || addr>=maxDevices)
techstep 0:8bdc990b1b57 164 return;
techstep 0:8bdc990b1b57 165 if(limit>=0 || limit<8)
techstep 0:8bdc990b1b57 166 spiTransfer(addr, OP_SCANLIMIT,limit);
techstep 0:8bdc990b1b57 167 }
techstep 0:8bdc990b1b57 168
techstep 0:8bdc990b1b57 169 void MAX72XX::setIntensity(int addr, int intensity) {
techstep 0:8bdc990b1b57 170 if(addr<0 || addr>=maxDevices)
techstep 0:8bdc990b1b57 171 return;
techstep 0:8bdc990b1b57 172 if(intensity>=0 || intensity<16)
techstep 0:8bdc990b1b57 173 spiTransfer(addr, OP_INTENSITY,intensity);
techstep 0:8bdc990b1b57 174 }
techstep 0:8bdc990b1b57 175
techstep 0:8bdc990b1b57 176 void MAX72XX::clearDigit(int addr, int digit) {
techstep 0:8bdc990b1b57 177 int offset;
techstep 0:8bdc990b1b57 178
techstep 0:8bdc990b1b57 179 if(addr<0 || addr>=maxDevices)
techstep 0:8bdc990b1b57 180 return;
techstep 0:8bdc990b1b57 181 //spiTransfer(addr, digit+1,0);
techstep 0:8bdc990b1b57 182 offset = addr*8;
techstep 0:8bdc990b1b57 183 for(int i=0;i<8;i++) {
techstep 0:8bdc990b1b57 184 status[offset+i] = 0;
techstep 0:8bdc990b1b57 185 spiTransfer(addr, digit+1,status[offset+i]);
techstep 0:8bdc990b1b57 186 }
techstep 0:8bdc990b1b57 187 }
techstep 0:8bdc990b1b57 188
techstep 0:8bdc990b1b57 189 void MAX72XX::clearDisplay(int addr) {
techstep 0:8bdc990b1b57 190 int offset;
techstep 0:8bdc990b1b57 191
techstep 0:8bdc990b1b57 192 if(addr<0 || addr>=maxDevices)
techstep 0:8bdc990b1b57 193 return;
techstep 0:8bdc990b1b57 194 offset = addr*8;
techstep 0:8bdc990b1b57 195 for(int i=0;i<8;i++) {
techstep 0:8bdc990b1b57 196 status[offset+i] = 0;
techstep 0:8bdc990b1b57 197 spiTransfer(addr, i+1,status[offset+i]);
techstep 0:8bdc990b1b57 198 }
techstep 0:8bdc990b1b57 199 }
techstep 0:8bdc990b1b57 200
techstep 0:8bdc990b1b57 201 void MAX72XX::setDigit(int addr, int digit, uint8_t value, bool dp) {
techstep 0:8bdc990b1b57 202 int offset;
techstep 0:8bdc990b1b57 203 uint8_t v;
techstep 0:8bdc990b1b57 204
techstep 0:8bdc990b1b57 205 if(addr<0 || addr>=maxDevices)
techstep 0:8bdc990b1b57 206 return;
techstep 0:8bdc990b1b57 207 if(digit<0 || digit>7 || value>15)
techstep 0:8bdc990b1b57 208 return;
techstep 0:8bdc990b1b57 209 offset = addr*8;
techstep 0:8bdc990b1b57 210 v = charTable[value];
techstep 0:8bdc990b1b57 211 if(dp)
techstep 0:8bdc990b1b57 212 v |= 0x80;
techstep 0:8bdc990b1b57 213 status[offset+digit]=v;
techstep 0:8bdc990b1b57 214 spiTransfer(addr, digit+1,v);
techstep 0:8bdc990b1b57 215 }
techstep 0:8bdc990b1b57 216
techstep 0:8bdc990b1b57 217 void MAX72XX::setChar(int addr, int digit, char value, bool dp) {
techstep 0:8bdc990b1b57 218 int offset;
techstep 0:8bdc990b1b57 219 uint8_t index,v;
techstep 0:8bdc990b1b57 220
techstep 0:8bdc990b1b57 221 if(addr<0 || addr>=maxDevices)
techstep 0:8bdc990b1b57 222 return;
techstep 0:8bdc990b1b57 223 if(digit<0 || digit>7)
techstep 0:8bdc990b1b57 224 return;
techstep 0:8bdc990b1b57 225 offset = addr*8;
techstep 0:8bdc990b1b57 226 index = value;
techstep 0:8bdc990b1b57 227 if(index >127) {
techstep 0:8bdc990b1b57 228 //no defined beyond index 127, so we use the space char
techstep 0:8bdc990b1b57 229 index = 32;
techstep 0:8bdc990b1b57 230 }
techstep 0:8bdc990b1b57 231 v = charTable[index];
techstep 0:8bdc990b1b57 232 if(dp)
techstep 0:8bdc990b1b57 233 v |= 0x80;
techstep 0:8bdc990b1b57 234 status[offset+digit] = v;
techstep 0:8bdc990b1b57 235 spiTransfer(addr, digit+1,v);
techstep 0:8bdc990b1b57 236 }
techstep 0:8bdc990b1b57 237
techstep 0:8bdc990b1b57 238 void MAX72XX::spiTransfer(int addr, volatile uint8_t opcode, volatile uint8_t data) {
techstep 0:8bdc990b1b57 239 //Create an array with the data to shift out
techstep 0:8bdc990b1b57 240 int offset = addr*2;
techstep 0:8bdc990b1b57 241 int maxbytes = maxDevices*2;
techstep 0:8bdc990b1b57 242
techstep 0:8bdc990b1b57 243 for(int i=0;i<maxbytes;i++)
techstep 0:8bdc990b1b57 244 spidata[i] = 0;
techstep 0:8bdc990b1b57 245 //put our device data into the array
techstep 0:8bdc990b1b57 246 spidata[offset+1] = opcode;
techstep 0:8bdc990b1b57 247 spidata[offset] = data;
techstep 0:8bdc990b1b57 248 //enable the line
techstep 0:8bdc990b1b57 249 cs = 0;
techstep 0:8bdc990b1b57 250 //Now shift out the data
techstep 0:8bdc990b1b57 251 for(int i=maxbytes;i>0;i--)
techstep 0:8bdc990b1b57 252 this->write(spidata[i-1]);
techstep 0:8bdc990b1b57 253 //latch the data onto the display
techstep 0:8bdc990b1b57 254 cs = 1;
techstep 0:8bdc990b1b57 255 }