├── Sprite16.h ├── examples ├── ReversalDemo │ └── ReversalDemo.ino ├── OrientationDemo │ └── OrientationDemo.ino └── DemoReel │ └── DemoReel.ino ├── Sprite16.cpp ├── LICENSE ├── HT16K33.h ├── README.textile └── HT16K33.cpp /Sprite16.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Quick and dirty 16-bit sprite library. 3 | */ 4 | 5 | #ifndef Sprite16_h 6 | 7 | // include appropriate version of Arduino code 8 | #if (ARDUINO >= 100) 9 | #include "Arduino.h" 10 | #else 11 | #include "WProgram.h" 12 | #endif 13 | 14 | #define Sprite16_h 15 | 16 | class Sprite16 17 | { 18 | public: 19 | Sprite16(uint8_t width, uint8_t height, uint16_t data, ...); 20 | uint8_t width(); 21 | uint8_t height(); 22 | uint16_t readRow(uint8_t row); 23 | 24 | private: 25 | uint8_t _height; 26 | uint8_t _width; 27 | uint16_t *_buffer; 28 | 29 | void init(uint8_t width, uint8_t height); 30 | }; 31 | #endif -------------------------------------------------------------------------------- /examples/ReversalDemo/ReversalDemo.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a quick demo of the reverse() functionality, which switches the order in which data bytes are sent to the 3 | * HT16K33, and is very useful if—like me—you wire your matrixes backward + really don’t want to have to redo everything. 4 | */ 5 | #include "HT16K33.h" 6 | #include "Sprite16.h" 7 | 8 | HT16K33 matrix = HT16K33(); 9 | Sprite16 one = Sprite16(3, 5, 2, 3, 2, 2, 7); 10 | Sprite16 two = Sprite16(3, 5, 2, 5, 4, 2, 7); 11 | 12 | void setup() 13 | { 14 | // start the matrix on I2C address 0x70 15 | matrix.init(0x70); 16 | 17 | // draw some quick identifiers 18 | matrix.drawSprite16(one, 3, 1); 19 | matrix.drawSprite16(two, 11, 1); 20 | 21 | } 22 | 23 | void loop() 24 | { 25 | // write everything the ‘correct’ way around 26 | matrix.write(); 27 | delay(2000); 28 | 29 | // reverse the order of the matrixes, write again 30 | matrix.reverse(); 31 | matrix.write(); 32 | delay(2000); 33 | 34 | // reset ready to try again 35 | matrix.resetOrientation(); 36 | } 37 | -------------------------------------------------------------------------------- /Sprite16.cpp: -------------------------------------------------------------------------------- 1 | #include "Sprite16.h" 2 | 3 | Sprite16::Sprite16(uint8_t width, uint8_t height, uint16_t data, ...) 4 | { 5 | // create everything 6 | init(width, height); 7 | 8 | // read in the data 9 | va_list ap; 10 | va_start(ap, data); 11 | for (uint8_t row = 0; ; row++) 12 | { 13 | _buffer[row] = data; 14 | 15 | if (row == _height - 1) 16 | { 17 | break; 18 | } 19 | 20 | data = va_arg(ap, uint16_t); 21 | } 22 | va_end(ap); 23 | } 24 | 25 | void Sprite16::init(uint8_t width, uint8_t height) 26 | { 27 | // store height and width 28 | _width = min(width, 16); 29 | _height = min(height, 8); 30 | 31 | // create the buffer 32 | _buffer = (uint16_t *)calloc(_height, sizeof(uint16_t)); 33 | } 34 | 35 | uint8_t Sprite16::height(void) 36 | { 37 | return _height; 38 | } 39 | 40 | uint8_t Sprite16::width(void) 41 | { 42 | return _width; 43 | } 44 | 45 | uint16_t Sprite16::readRow(uint8_t row) 46 | { 47 | if (row > _height) 48 | { 49 | return 0; 50 | } 51 | 52 | return _buffer[row]; 53 | } -------------------------------------------------------------------------------- /examples/OrientationDemo/OrientationDemo.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a quick demo of the orientation settings for this library, which allow you to flip matrices in software 3 | * without having to do much in the way of hard work. 4 | */ 5 | #include "HT16K33.h" 6 | 7 | HT16K33 matrix = HT16K33(); 8 | 9 | void setup() 10 | { 11 | // start the matrix on I2C address 0x70 12 | matrix.init(0x70); 13 | 14 | // draw an arrow on the display 15 | matrix.setRow(1, 30); 16 | matrix.setRow(2, 2); 17 | matrix.setRow(3, 10); 18 | matrix.setRow(4, 18); 19 | matrix.setRow(5, 32); 20 | 21 | // hold off 22 | delay(100); 23 | } 24 | 25 | void loop() 26 | { 27 | // show it the right way around 28 | matrix.write(); 29 | delay(2000); 30 | 31 | // flip horizontally 32 | matrix.flipHorizontal(); 33 | matrix.write(); 34 | delay(2000); 35 | matrix.resetOrientation(); 36 | 37 | // flip vertically 38 | matrix.flipVertical(); 39 | matrix.write(); 40 | delay(2000); 41 | matrix.resetOrientation(); 42 | 43 | // flipping both ways: this is the same as rotating through 180° 44 | matrix.flipHorizontal(); 45 | matrix.flipVertical(); 46 | matrix.write(); 47 | delay(2000); 48 | matrix.resetOrientation(); 49 | } 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to -------------------------------------------------------------------------------- /HT16K33.h: -------------------------------------------------------------------------------- 1 | #ifndef HT16K33_h 2 | #define HT16K33_h 3 | 4 | // include appropriate version of Arduino code 5 | #if (ARDUINO >= 100) 6 | #include "Arduino.h" 7 | #else 8 | #include "WProgram.h" 9 | #endif 10 | 11 | // include Wire for I2C comms 12 | #include 13 | #include "Sprite16.h" 14 | 15 | // different commands 16 | #define HT16K33_CMD_RAM 0x00 17 | #define HT16K33_CMD_KEYS 0x40 18 | #define HT16K33_CMD_SETUP 0x80 19 | #define HT16K33_CMD_ROWINT 0xA0 20 | #define HT16K33_CMD_DIMMING 0xE0 21 | 22 | // other options 23 | #define HT16K33_DISPLAY_OFF 0x00 24 | #define HT16K33_DISPLAY_ON 0x01 25 | #define HT16K33_BLINK_OFF 0x00 26 | #define HT16K33_BLINK_1HZ 0x02 27 | #define HT16K33_BLINK_2HZ 0x04 28 | #define HT16K33_BLINK_0HZ5 0x06 29 | 30 | 31 | // actual class 32 | class HT16K33 33 | { 34 | public: 35 | void init(uint8_t addr); 36 | 37 | // brightness control 38 | void setBrightness(uint8_t brightness); 39 | 40 | // blink controls 41 | void setBlink(uint8_t blink); 42 | 43 | // orientation 44 | void resetOrientation(void); 45 | void reverse(void); 46 | void flipVertical(void); 47 | void flipHorizontal(void); 48 | 49 | // buffer stuff 50 | void clear(void); 51 | void setPixel(uint8_t row, uint8_t col, uint8_t onff); 52 | void setRow(uint8_t row, uint16_t value); 53 | void setColumn(uint8_t col, uint8_t value); 54 | void drawSprite16(Sprite16 data, uint8_t colOffset, uint8_t rowOffset); 55 | void drawSprite16(Sprite16 data); 56 | 57 | // read/write 58 | void write(void); 59 | 60 | private: 61 | uint16_t *_buffer; 62 | uint8_t _i2c_addr; 63 | bool _reversed; 64 | bool _vFlipped; 65 | bool _hFlipped; 66 | 67 | void writeRow(uint8_t row); 68 | 69 | }; 70 | 71 | #endif // #HT16K33 72 | -------------------------------------------------------------------------------- /examples/DemoReel/DemoReel.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a quick and dirty demo/test to demonstrate how to set rows, 3 | * columns, and individual pixels, as well as drawing sprites on a 16x8 4 | * matrix. 5 | * 6 | * Note that this will work fine with an 8x8 matrix or even a bicolour 7 | * matrix… although the latter might look a little strange. 8 | */ 9 | #include "HT16K33.h" 10 | 11 | HT16K33 matrix = HT16K33(); 12 | Sprite16 smile = Sprite16( 6, 6, 18, 18, 0, 0, 33, 30); 13 | Sprite16 frown = Sprite16( 6, 6, 18, 18, 0, 0, 30, 33); 14 | 15 | void setup() 16 | { 17 | // start the matrix on I2C address 0x70 18 | matrix.init(0x70); 19 | delay(1000); 20 | } 21 | 22 | void loop() 23 | { 24 | // draw some sprites 25 | matrix.drawSprite16(smile, 1, 1); 26 | matrix.drawSprite16(frown, 9, 1); 27 | matrix.write(); 28 | 29 | // fade in 30 | int brt; 31 | for (brt = 0; brt < 16; brt++) 32 | { 33 | matrix.setBrightness(brt); 34 | delay(10); 35 | } 36 | delay(1000); 37 | for (brt = 15; brt >= 0; brt--) 38 | { 39 | matrix.setBrightness(brt); 40 | delay(10); 41 | } 42 | matrix.clear(); 43 | matrix.setBrightness(15); 44 | 45 | // draw some spirals 46 | spiral8(0, 1); 47 | spiral8(8, 1); 48 | spiral16(0); 49 | delay(200); 50 | 51 | // wipe 52 | uint8_t row; 53 | matrix.clear(); 54 | for (row = 0; row < 8; row++) 55 | { 56 | matrix.setRow(row, 0xFFFF); 57 | matrix.write(); 58 | delay(50); 59 | } 60 | for (row = 0; row < 8; row++) 61 | { 62 | matrix.setRow(row, 0); 63 | matrix.write(); 64 | delay(50); 65 | } 66 | 67 | // another wipe 68 | uint8_t col; 69 | for (col = 0; col < 16; col++) 70 | { 71 | matrix.setColumn(col, 0xFF); 72 | matrix.write(); 73 | delay(50); 74 | } 75 | for (col = 0; col < 16; col++) 76 | { 77 | matrix.setColumn(col, 0); 78 | matrix.write(); 79 | delay(50); 80 | } 81 | delay(1000); 82 | matrix.clear(); 83 | } 84 | 85 | void spiral8(uint8_t start, uint8_t value) 86 | { 87 | //start looping 88 | int row; 89 | int col; 90 | for (int fiddle = 0; fiddle < 4; fiddle++) 91 | { 92 | for (row = (start + fiddle); row < (start + (7 - fiddle)); row++) { pixel(row, fiddle, value); } 93 | for (col = fiddle; col < (7 - fiddle); col++) { pixel(start + (7 - fiddle), col, value); } 94 | for (row = (start + (7 - fiddle)); row > (start + fiddle); row--) { pixel(row, (7-fiddle), value); } 95 | for (col = (7 - fiddle); col > fiddle; col--) { pixel(start + fiddle, col, value); } 96 | } 97 | } 98 | 99 | void spiral16(uint8_t value) 100 | { 101 | //start looping 102 | int row; 103 | int col; 104 | for (int fiddle = 0; fiddle < 4; fiddle++) 105 | { 106 | for (row = fiddle; row < (15 - fiddle); row++) { pixel(row, fiddle, value); } 107 | for (col = fiddle; col < (7 - fiddle); col++) { pixel((15 - fiddle), col, value); } 108 | for (row = (15 - fiddle); row > fiddle; row--) { pixel(row, (7 - fiddle), value); } 109 | for (col = (7 - fiddle); col > fiddle; col--) { pixel(fiddle, col, value); } 110 | } 111 | } 112 | 113 | void pixel( uint8_t row, uint8_t col, uint8_t val ) 114 | { 115 | matrix.setPixel(row, col, val); 116 | matrix.write(); 117 | delay(10); 118 | } -------------------------------------------------------------------------------- /README.textile: -------------------------------------------------------------------------------- 1 | h1. HT16K33 Library for Arduino 2 | 3 | This is a quick and dirty library providing a relatively easy-to-use interface for driving the "Holtek HT16K33":http://www.holtek.com.tw/documents/10179/11842/HT16K33v120.pdf 16x8 LED driver IC. I wrote it for a project I was working on, and thought it worth chucking up onto Github in case anyone else finds it useful. 4 | 5 | h2. Quickref 6 | 7 | This library should be reasonably self-explanatory, and I’ve provided a few example sketches to get you started: 8 | 9 | * *DemoReel* is your standard ‘smily faces and random animation’ thing that most matrix libraries tend to come with 10 | * *OrientationDemo* demonstrates the library’s ability to quickly + easily flip the display vertically + horizontally in software with a minimum of fuss and bother 11 | * *ReversalDemo* demonstrates how you can recover from connecting your matrices backward =) 12 | 13 | The API commands are, in no particular order: 14 | 15 | - @init(uint8_t i2c_addr)@ := specifies the "I2C":https://en.wikipedia.org/wiki/I%C2%B2C address of the IC 16 | - @setBrightness(uint8_t b)@ := sets the brightness of the display (0–15) 17 | - @setBlink(uint8_t)@ := sets the blink rate of the display (see note below) 18 | - @resetOrientation()@ := resets the orientation of the display to the defaults 19 | - @reverse()@ := reverses the order of the two 8x8 sub-matrices (again, see note below) 20 | - @flipVertical()@ := flips the matrix data vertically before writing to the IC 21 | - @flipHorizontal()@ := flips the matrix data horizontally before writing to the IC 22 | - @clear()@ := clears the matrix completely† 23 | - @setPixel(uint8_t row, uint8_t col, uint8_t onoff)@ := sets the state of a single pixel. @onoff@ should be either 0 (off) or 1 (on)† 24 | - @setRow(uint8_t row, uint16_t value)@ := sets the content of an entire row (16 bits)† 25 | - @setColumn(uint8_t col, uint8_t value)@ := sets the content of an entire column (8 bits)† 26 | - @drawSprite16(Sprite16 data)@ := draws the @Sprite16@ onto the matrix at point (0, 0) (see below)† 27 | - @drawSprite16(Sprite16 data, uint8_t x, uint8_t y)@ := as above, but at point (x, y)† 28 | - @write()@ := writes the display buffer to the IC (updates the display) 29 | 30 | † note: none of these will write anything to the IC—you will still need to call @write()@. 31 | 32 | h3. About @Sprite16@ 33 | 34 | @Sprite16@ is a class based on the venerable "Sprite library":http://wiring.org.co/reference/libraries/Sprite/index.html, but which has been built to allow a maximum sprite size of 16x8, compared to 8x8 in the original. 35 | 36 | In terms of creating sprites, Sprite16 is virtually identical to the original: 37 | 38 | pre. Sprite16 smile = Sprite16( 5, 5, 10, 10, 0, 17, 14 ); 39 | 40 | p. However, one major difference is that Sprite16 _does not_ implement either the @read()@ or @write()@ methods present 41 | in the original, as it is unneeded for the purposes of this library. 42 | 43 | h3. Blink Rates 44 | 45 | For various reasons, blink rates are #define-d as a set of constants: 46 | 47 | - @HT16K33_BLINK_OFF@ := disable blinking (default) 48 | - @HT16K33_BLINK_1HZ@ := set blink rate to 1Hz 49 | - @HT16K33_BLINK_2HZ@ := set blink rate to 2Hz 50 | - @HT16K33_BLINK_0HZ5@ := set blink rate to 0.5Hz 51 | 52 | h3. Matrix reversal 53 | 54 | _This only really makes sense if you’re using a 16x8 matrix made of two discrete 8x8 matrixes. If you’re rolling it yourself or using a single 16x8, you may as well ignore this section._ 55 | 56 | This library assumes that, if you’re using two 8x8 matrixes, you’ve wired them correctly with ROW0 on the left-hand edge of the left-most matrix, and ROW15 on the right-most edge, thus: 57 | 58 | pre. 59 | 0 7 8 15 60 | +--------+--------+ 61 | | | | 62 | | | | 63 | | | | 64 | +--------+--------+ 65 | 66 | p. However, just occasionally your concentration will slip and you’ll end up with something like this: 67 | 68 | pre. 69 | 8 15 0 7 70 | +--------+--------+ 71 | | | | 72 | | | | 73 | | | | 74 | +--------+--------+ 75 | 76 | p. Rather than having to rewire everything/rework your PCBs, you can just call @reverse()@, and the library will cover for you… 77 | 78 | _(no, this didn’t happen to me. I don’t know why you would think that /s)_ 79 | 80 | h2. TODO 81 | 82 | It’d be really nice if this library supported the HT16K33’s keyscan functionality… 83 | 84 | h2. Caveats 85 | 86 | As mentioned at the start, I wrote this library for fun and to scratch a particular itch. I’m offering it to the world Because™, but I make no guarantee that it’s going to work 100% perfectly every time. By the same token, I’m not going to offer any kind of guarantee that I’ll touch this repo once I’ve made my first commit :) 87 | 88 | All of this means that while you’re free to use/modify/etc everything here with/without attribution, you do so at your own risk and I am not responsible for what you get up to: if it breaks/catches fire/gains sentience and steals your cat, that’s all on you =) 89 | (although I will accept sensible PRs if you find any particularly egregious issues…) 90 | 91 | That said, if you do do something particularly Nifty™ with this library, I’ve love to hear from you—I’m on Twitter "@jonpearse":https://twitter.com/jonpearse 92 | 93 | … 94 | 95 | Share and enjoy! 96 | -------------------------------------------------------------------------------- /HT16K33.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * This is a quick library for the Holtek HT16K33 LED driver + keyscan 4 | * IC. It’s not functionally exhaustive by any stretch, but it should 5 | * at least work reasonably well. 6 | * 7 | * @TODO: build functionality to read key data from the chip. 8 | * 9 | **********************************************************************/ 10 | #include 11 | #include "HT16K33.h" 12 | 13 | /** 14 | * Utility function to flip a 16-bit integer. There may be better ways of doing this—let me know! 15 | */ 16 | uint16_t _flip_uint16(uint16_t in) 17 | { 18 | uint16_t out = 0; 19 | 20 | for (uint8_t i = 0; i < 16; i++) 21 | { 22 | out <<= 1; 23 | out |= in & 1; 24 | in >>= 1; 25 | } 26 | 27 | return out; 28 | } 29 | 30 | // Constructor 31 | void HT16K33::init(uint8_t addr) 32 | { 33 | // orientation flags 34 | resetOrientation(); 35 | 36 | // set the I2C address 37 | _i2c_addr = addr; 38 | 39 | // assign + zero some buffer data 40 | _buffer = (uint16_t*)calloc(8, sizeof(uint16_t)); 41 | 42 | // start everything 43 | Wire.begin(); 44 | Wire.beginTransmission(_i2c_addr); 45 | Wire.write(0x21); // turn it on 46 | Wire.endTransmission(); 47 | 48 | // set blink off + brightness all the way up 49 | setBlink(HT16K33_BLINK_OFF); 50 | setBrightness(15); 51 | 52 | // write the matrix, just in case 53 | write(); 54 | } 55 | 56 | /** 57 | * Sets the brightness of the display. 58 | */ 59 | void HT16K33::setBrightness(uint8_t brightness) 60 | { 61 | // constrain the brightness to a 4-bit number (0–15) 62 | brightness = brightness & 0x0F; 63 | 64 | // send the command 65 | Wire.beginTransmission(_i2c_addr); 66 | Wire.write(HT16K33_CMD_DIMMING | brightness); 67 | Wire.endTransmission(); 68 | } 69 | 70 | /** 71 | * Set the blink rate. 72 | */ 73 | void HT16K33::setBlink(uint8_t blink) 74 | { 75 | Wire.beginTransmission(_i2c_addr); 76 | Wire.write(HT16K33_CMD_SETUP | HT16K33_DISPLAY_ON | blink); 77 | Wire.endTransmission(); 78 | } 79 | 80 | /** 81 | * Reset the matrix orientation./ 82 | */ 83 | void HT16K33::resetOrientation(void) 84 | { 85 | _reversed = false; 86 | _vFlipped = false; 87 | _hFlipped = false; 88 | } 89 | 90 | /** 91 | * Flips the order of the two 8x8 matrices: useful if you’ve wired them backward by mistake =) 92 | */ 93 | void HT16K33::reverse(void) 94 | { 95 | _reversed = !_reversed; 96 | } 97 | 98 | /** 99 | * Flips the vertical orientation of the matrices. 100 | */ 101 | void HT16K33::flipVertical(void) 102 | { 103 | _vFlipped = !_vFlipped; 104 | } 105 | 106 | /** 107 | * Flips the vertical orientation of the matrices. 108 | */ 109 | void HT16K33::flipHorizontal(void) 110 | { 111 | _hFlipped = !_hFlipped;; 112 | } 113 | 114 | 115 | /** 116 | * Clears the display buffer. Note that this doesn’t clear the display—you’ll need to call write() to do this. 117 | */ 118 | void HT16K33::clear(void) 119 | { 120 | for (uint8_t i = 0; i < 8; i++) 121 | { 122 | _buffer[i] = 0; 123 | } 124 | } 125 | 126 | /** 127 | * Sets the value of a particular pixel. 128 | */ 129 | void HT16K33::setPixel(uint8_t col, uint8_t row, uint8_t val) 130 | { 131 | // bounds checking 132 | col = col & 0x0F; 133 | row = row & 0x07; 134 | val = val & 0x01; 135 | 136 | // write the buffer 137 | if (val == 1) 138 | { 139 | _buffer[row] |= 1 << col; 140 | } 141 | else 142 | { 143 | _buffer[row] &= ~(1 << col); 144 | } 145 | 146 | } 147 | 148 | /** 149 | * Sets the value of an entire row. 150 | */ 151 | void HT16K33::setRow(uint8_t row, uint16_t value) 152 | { 153 | // bound check the row 154 | row = row & 0x07; 155 | 156 | // write it 157 | _buffer[row] = value; 158 | } 159 | 160 | /** 161 | * Set the value of an entire column. This is more fun =) 162 | */ 163 | void HT16K33::setColumn(uint8_t col, uint8_t value) 164 | { 165 | // just do this via set pixel—waaaay easier! 166 | for (uint8_t row = 0; row < 8; row++) 167 | { 168 | setPixel(col, row, (value & (1 << row)) > 0); 169 | } 170 | } 171 | 172 | /** 173 | * Bulk-writes a set of row data to the display. 174 | */ 175 | void HT16K33::drawSprite16(Sprite16 sprite, uint8_t colOffset, uint8_t rowOffset) 176 | { 177 | // iterate through data and set stuff 178 | for (uint8_t row = 0; row < sprite.height(); row++) 179 | { 180 | _buffer[(row + rowOffset) & 0x07] |= (sprite.readRow(row) << colOffset) & 0xFFFF; 181 | } 182 | 183 | } 184 | 185 | /** 186 | * Same as the above, just without offsets. 187 | */ 188 | void HT16K33::drawSprite16(Sprite16 sprite) 189 | { 190 | drawSprite16(sprite, 0, 0); 191 | } 192 | 193 | /** 194 | * Write the RAM buffer to the matrix. 195 | */ 196 | void HT16K33::write(void) 197 | { 198 | Wire.beginTransmission(_i2c_addr); 199 | Wire.write(HT16K33_CMD_RAM); 200 | 201 | for (uint8_t row = 0; row < 8; row++) 202 | { 203 | writeRow(row); 204 | } 205 | 206 | Wire.endTransmission(); 207 | } 208 | 209 | /** 210 | * Write a row to the chip. 211 | */ 212 | void HT16K33::writeRow(uint8_t row) 213 | { 214 | // flip vertically 215 | if (_vFlipped) 216 | { 217 | row = 7 - row; 218 | } 219 | 220 | // read out the buffer so we can flip horizontally 221 | uint16_t out = _buffer[row]; 222 | if (_hFlipped) 223 | { 224 | out = _flip_uint16(out); 225 | } 226 | 227 | if (_reversed) 228 | { 229 | Wire.write(out >> 8); // second byte 230 | Wire.write(out & 0xFF); // first byte 231 | } 232 | else 233 | { 234 | Wire.write(out & 0xFF); // first byte 235 | Wire.write(out >> 8); // second byte 236 | } 237 | } --------------------------------------------------------------------------------