~ubuntu-branches/ubuntu/precise/arduino/precise

« back to all changes in this revision

Viewing changes to libraries/Matrix/Matrix.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Howard
  • Date: 2010-04-13 22:32:24 UTC
  • Revision ID: james.westby@ubuntu.com-20100413223224-jduxnd0xxnkkda02
Tags: upstream-0018+dfsg
ImportĀ upstreamĀ versionĀ 0018+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Matrix.cpp - Max7219 LED Matrix library for Arduino & Wiring
 
3
  Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
 
4
 
 
5
  This library is free software; you can redistribute it and/or
 
6
  modify it under the terms of the GNU Lesser General Public
 
7
  License as published by the Free Software Foundation; either
 
8
  version 2.1 of the License, or (at your option) any later version.
 
9
 
 
10
  This library is distributed in the hope that it will be useful,
 
11
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
  Lesser General Public License for more details.
 
14
 
 
15
  You should have received a copy of the GNU Lesser General Public
 
16
  License along with this library; if not, write to the Free Software
 
17
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
*/
 
19
 
 
20
// TODO: Support segment displays in api?
 
21
// TODO: Support varying vendor layouts?
 
22
 
 
23
/******************************************************************************
 
24
 * Includes
 
25
 ******************************************************************************/
 
26
 
 
27
extern "C" {
 
28
  // AVR LibC Includes
 
29
  #include <inttypes.h>
 
30
  #include <stdlib.h>
 
31
 
 
32
  // Wiring Core Includes
 
33
  #undef abs
 
34
  #include "WConstants.h"
 
35
 
 
36
  // Wiring Core Prototypes
 
37
  //void pinMode(uint8_t, uint8_t);
 
38
  //void digitalWrite(int, uint8_t);
 
39
}
 
40
 
 
41
#include "Sprite.h"
 
42
#include "Matrix.h"
 
43
 
 
44
/******************************************************************************
 
45
 * Definitions
 
46
 ******************************************************************************/
 
47
 
 
48
// Matrix registers
 
49
#define REG_NOOP   0x00
 
50
#define REG_DIGIT0 0x01
 
51
#define REG_DIGIT1 0x02
 
52
#define REG_DIGIT2 0x03
 
53
#define REG_DIGIT3 0x04
 
54
#define REG_DIGIT4 0x05
 
55
#define REG_DIGIT5 0x06
 
56
#define REG_DIGIT6 0x07
 
57
#define REG_DIGIT7 0x08
 
58
#define REG_DECODEMODE  0x09
 
59
#define REG_INTENSITY   0x0A
 
60
#define REG_SCANLIMIT   0x0B
 
61
#define REG_SHUTDOWN    0x0C
 
62
#define REG_DISPLAYTEST 0x0F
 
63
 
 
64
/******************************************************************************
 
65
 * Constructors
 
66
 ******************************************************************************/
 
67
 
 
68
Matrix::Matrix(uint8_t data, uint8_t clock, uint8_t load, uint8_t screens /* = 1 */)
 
69
{
 
70
  // record pins for sw spi
 
71
  _pinData = data;
 
72
  _pinClock = clock;
 
73
  _pinLoad = load;
 
74
 
 
75
  // set ddr for sw spi pins
 
76
  pinMode(_pinClock, OUTPUT);
 
77
  pinMode(_pinData, OUTPUT);
 
78
  pinMode(_pinLoad, OUTPUT);
 
79
 
 
80
  // allocate screenbuffers
 
81
  _screens = screens;
 
82
  _buffer = (uint8_t*)calloc(_screens, 64);
 
83
  _maximumX = (_screens * 8);
 
84
 
 
85
  // initialize registers
 
86
  clear();             // clear display
 
87
  setScanLimit(0x07);  // use all rows/digits
 
88
  setBrightness(0x0F); // maximum brightness
 
89
  setRegister(REG_SHUTDOWN, 0x01);    // normal operation
 
90
  setRegister(REG_DECODEMODE, 0x00);  // pixels not integers
 
91
  setRegister(REG_DISPLAYTEST, 0x00); // not in test mode
 
92
}
 
93
 
 
94
/******************************************************************************
 
95
 * MAX7219 SPI
 
96
 ******************************************************************************/
 
97
 
 
98
// sends a single byte by sw spi (no latching)
 
99
void Matrix::putByte(uint8_t data)
 
100
{
 
101
  uint8_t i = 8;
 
102
  uint8_t mask;
 
103
  while(i > 0) {
 
104
    mask = 0x01 << (i - 1);         // get bitmask
 
105
    digitalWrite(_pinClock, LOW);   // tick
 
106
    if (data & mask){               // choose bit
 
107
      digitalWrite(_pinData, HIGH); // set 1
 
108
    }else{
 
109
      digitalWrite(_pinData, LOW);  // set 0
 
110
    }
 
111
    digitalWrite(_pinClock, HIGH);  // tock
 
112
    --i;                            // move to lesser bit
 
113
  }
 
114
}
 
115
 
 
116
// sets register to a byte value for all screens
 
117
void Matrix::setRegister(uint8_t reg, uint8_t data)
 
118
{
 
119
  digitalWrite(_pinLoad, LOW); // begin
 
120
  for(uint8_t i = 0; i < _screens; ++i){
 
121
    putByte(reg);  // specify register
 
122
    putByte(data); // send data
 
123
  }
 
124
  digitalWrite(_pinLoad, HIGH);  // latch in data
 
125
  digitalWrite(_pinLoad, LOW); // end
 
126
}
 
127
 
 
128
// syncs row of display with buffer
 
129
void Matrix::syncRow(uint8_t row)
 
130
{
 
131
  if (!_buffer) return;
 
132
  
 
133
  // uint8_t's can't be negative, so don't test for negative row
 
134
  if (row >= 8) return;
 
135
  digitalWrite(_pinLoad, LOW); // begin
 
136
  for(uint8_t i = 0; i < _screens; ++i){
 
137
    putByte(8 - row);                // specify register
 
138
    putByte(_buffer[row + (8 * i)]); // send data
 
139
  }
 
140
  digitalWrite(_pinLoad, HIGH);  // latch in data
 
141
  digitalWrite(_pinLoad, LOW); // end
 
142
}
 
143
 
 
144
/******************************************************************************
 
145
 * MAX7219 Configuration
 
146
 ******************************************************************************/
 
147
 
 
148
// sets how many digits are displayed
 
149
void Matrix::setScanLimit(uint8_t value)
 
150
{
 
151
  setRegister(REG_SCANLIMIT, value & 0x07);
 
152
}
 
153
 
 
154
// sets brightness of the display
 
155
void Matrix::setBrightness(uint8_t value)
 
156
{
 
157
  setRegister(REG_INTENSITY, value & 0x0F);
 
158
}
 
159
 
 
160
/******************************************************************************
 
161
 * Helper Functions
 
162
 ******************************************************************************/
 
163
 
 
164
void Matrix::buffer(uint8_t x, uint8_t y, uint8_t value)
 
165
{
 
166
  if (!_buffer) return;
 
167
  
 
168
  // uint8_t's can't be negative, so don't test for negative x and y.
 
169
  if (x >= _maximumX || y >= 8) return;
 
170
 
 
171
  uint8_t offset = x; // record x
 
172
  x %= 8;             // make x relative to a single matrix
 
173
  offset -= x;        // calculate buffer offset
 
174
 
 
175
  // wrap shift relative x for nexus module layout
 
176
  if (x == 0){
 
177
    x = 8;
 
178
  }
 
179
  --x;
 
180
 
 
181
  // record value in buffer
 
182
  if(value){
 
183
    _buffer[y + offset] |= 0x01 << x;
 
184
  }else{
 
185
    _buffer[y + offset] &= ~(0x01 << x);
 
186
  }
 
187
}
 
188
 
 
189
/******************************************************************************
 
190
 * User API
 
191
 ******************************************************************************/
 
192
 
 
193
// buffers and writes to screen
 
194
void Matrix::write(uint8_t x, uint8_t y, uint8_t value)
 
195
{
 
196
  buffer(x, y, value);
 
197
  
 
198
  // update affected row
 
199
  syncRow(y);
 
200
}
 
201
 
 
202
void Matrix::write(uint8_t x, uint8_t y, Sprite sprite)
 
203
{
 
204
  for (uint8_t i = 0; i < sprite.height(); i++){
 
205
    for (uint8_t j = 0; j < sprite.width(); j++)
 
206
      buffer(x + j, y + i, sprite.read(j, i));
 
207
      
 
208
    syncRow(y + i);
 
209
  }
 
210
}
 
211
 
 
212
// clears screens and buffers
 
213
void Matrix::clear(void)
 
214
{
 
215
  if (!_buffer) return;
 
216
 
 
217
  // clear buffer
 
218
  for(uint8_t i = 0; i < 8; ++i){
 
219
    for(uint8_t j = 0; j < _screens; ++j){
 
220
      _buffer[i + (8 * j)] = 0x00;
 
221
    }
 
222
  }
 
223
 
 
224
  // clear registers
 
225
  for(uint8_t i = 0; i < 8; ++i){
 
226
    syncRow(i);
 
227
  }
 
228
}
 
229