Library for Sure Electronics HT1632 based LED matrix displays. Supports multiple displays connected together.

Dependents:   HT1632MsgScroller SMS_LEDMatrixPrinter

Files at this revision

API Documentation at this revision

Comitter:
SomeRandomBloke
Date:
Thu Nov 08 21:41:33 2012 +0000
Child:
1:96695118ee13
Child:
7:b761bf1362ac
Commit message:
Initial commit after converting from Arduino to mbed

Changed in this revision

HT1632_LedMatrix.cpp Show annotated file Show diff for this revision Revisions of this file
HT1632_LedMatrix.h Show annotated file Show diff for this revision Revisions of this file
font_5x7_p.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HT1632_LedMatrix.cpp	Thu Nov 08 21:41:33 2012 +0000
@@ -0,0 +1,655 @@
+/***********************************************************************
+ * HT1632_LedMatrix.cpp - Arduino library for Holtek HT1632 LED driver chip,
+ *     As implemented on the Sure Electronics DE-DP10X display board
+ *       (8 x 32 dot matrix LED module.)
+ *
+ * Original code by:
+ * Nov, 2008 by Bill Westfield ("WestfW")
+ *   Copyrighted and distributed under the terms of the Berkely license
+ *   (copy freely, but include this notice of original author.)
+ *
+ * Adapted for 8x32 display by FlorinC.
+ *
+ * Library Created and updated by Andrew Lindsay October/November 2009
+ ***********************************************************************/
+
+#include "mbed.h"
+#include "HT1632_LedMatrix.h"
+#include "font_5x7_p.h"
+
+// Use this define to select Direct port writes for speed or regular arduino digitalWrite functions
+#undef DIRECTIO
+
+#define HIGH 1
+#define LOW 0
+/*
+ * Set these constants to the values of the pins connected to the SureElectronics Module
+ * NOTE - these are different from the original demo code by westfw
+ *
+ * Use Pin Mappings 8-11 for CS1 to 4, 12 for Data and 13 for Clock
+ * Use mixture of #define and variables.
+ * Pin numbers are for setup and port identifiers are for direct port writes.
+ */
+
+// For mbed, use WR=p7, DATA=p5, cs1=p17, cs2=p18, cs3=p19, cs4=p20
+
+//#define LOWPINS
+//#define LOWPINS1
+//#define HIGHPINS
+
+//#ifdef LOWPINS
+DigitalOut ht1632_wrclk(p7); // For Test : Led1 is Clock
+DigitalOut ht1632_data(p5); //            Led2 is Data ....
+DigitalOut ht1632_cs1(p17);
+DigitalOut ht1632_cs2(p18);
+DigitalOut ht1632_cs3(p19);
+DigitalOut ht1632_cs4(p20);
+
+// Port D defines for 2-7
+// If using Nuelectronics ethernet shield, need to cut unused interrupt track to PD2
+//uint8_t ht1632_cs[4] = {ht1632_cs1, ht1632_cs2, ht1632_cs3, ht1632_cs4};    // Chip Select (1, 2, 3, or 4)
+DigitalOut  ht1632_cs[4] = {p17, p18, p19, p20};    // Chip Select (1, 2, 3, or 4)
+//volatile uint8_t* ht1632_cs_Port[4] = {&PORTD, &PORTD, &PORTD, &PORTD};    // Chip Select (1, 2, 3, or 4)
+//volatile uint8_t* ht1632_cs_DDR[4] = {&DDRD, &DDRD, &DDRD, &DDRD};    // Chip Select (1, 2, 3, or 4)
+//#define HT1632_DATA       6      // Data pin
+//#define HT1632_DATA_PORT  PORTD  // Data port
+//#define HT1632_DATA_DDR   DDRD   // Data port
+//#define HT1632_WRCLK      7      // Write clock pin
+//#define HT1632_WRCLK_PORT PORTD  // Write clock port
+//#define HT1632_WRCLK_DDR  DDRD   // Write clock port
+//#endif
+
+
+// helper macros
+//#define output_low(port,pin) port &= ~(1<<pin)
+//#define output_high(port,pin) port |= (1<<pin)
+#define chip_number(x,y) (x >> 5) + (y >> 3)*numYDevices
+#define chip_nibble_address(x,y) ((x%32)<<1) + ((y%8)>>2);  
+#define chip_byte_address(x,y) ((x%32)<<1);
+#define max(a, b)  (((a) > (b)) ? (a) : (b))
+
+
+// Display size and configuration, defaul is for a single 8x32 display
+uint8_t numDevices = 1;    // Total number of devices
+uint8_t numXDevices = 1;   // Number of horizontal devices
+uint8_t numYDevices = 1;   // Number of vertical devices
+uint8_t xMax = 32 * numXDevices-1;
+uint8_t yMax = 8 * numYDevices-1;
+
+// Variables used to keep track of cursor position
+int cursorX = 0;
+int cursorY = 0;
+
+/*
+ * we keep a copy of the display controller contents so that we can
+ * know which bits are on without having to (slowly) read the device.
+ */
+// 4 boards at 32 bytes per board + 1 byte means we don't need to check overwrite in putChar
+uint8_t shadowram[129];  // our copy of the display's RAM
+
+
+
+// Custom character buffers - 8 characters available
+// 6 cols * 8 rows - first byte of each char is the number of columns used
+// Bits are aranged in columns with LSB at top
+uint8_t cgram [8][7] = { 
+    { 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
+
+
+// Default constructor
+HT1632_LedMatrix::HT1632_LedMatrix( void ) {
+}
+
+
+void HT1632_LedMatrix::init( uint8_t xDevices, uint8_t yDevices ) {
+  // Set up the display size based on number of devices both horizontal and vertical
+  numXDevices = xDevices;
+  xMax = 32 * numXDevices-1;
+  numYDevices = yDevices;
+  yMax = 8 * numYDevices-1;
+
+  numDevices = numXDevices * numYDevices;
+
+//  HT1632_WRCLK_DDR |= _BV( HT1632_WRCLK );      // set pins to output
+//  HT1632_DATA_DDR |= _BV( HT1632_DATA );
+
+  for (uint8_t chipno=0; chipno<numDevices; chipno++){
+ //     *ht1632_cs_DDR[chipno] |= _BV( ht1632_cs[chipno] );   // output pin
+      chipfree(chipno);     // unselect it 
+      sendcmd(chipno, HT1632_CMD_SYSDIS);  // Disable system
+      sendcmd(chipno, HT1632_CMD_COMS10);  // 08*32, PMOS drivers
+      sendcmd(chipno, HT1632_CMD_MSTMD);    // Master Mode 
+      sendcmd(chipno, HT1632_CMD_SYSON);    // System on 
+      sendcmd(chipno, HT1632_CMD_LEDON);    // LEDs on 
+      sendcmd(chipno, HT1632_CMD_PWM | 0x0c);   // PWM Duty 
+      for (uint8_t i=0; i<96; i++)
+        senddata(chipno, i, 0);  // clear the display
+      wait(0.1);
+  }
+  cursorX = 0;
+  cursorY = 0;
+}
+ 
+/***********************************************************************
+ * chipselect / chipfree
+ * Select or de-select a particular ht1632 chip.
+ * De-selecting a chip ends the commands being sent to a chip.
+ * CD pins are active-low; writing 0 to the pin selects the chip.
+ ***********************************************************************/
+void HT1632_LedMatrix::chipselect(uint8_t chipno)
+{
+#ifdef DIRECTIO
+//  output_low(*ht1632_cs_Port[chipno], ht1632_cs[chipno]);
+#else
+//  digitalWrite( ht1632_cs[chipno], LOW );
+  
+#endif
+//ht1632_cs4 = LOW;
+    ht1632_cs[chipno] = LOW;
+}
+
+void HT1632_LedMatrix::chipfree(uint8_t chipno)
+{
+#ifdef DIRECTIO
+//  output_high(*ht1632_cs_Port[chipno], ht1632_cs[chipno]);
+#else
+//  digitalWrite( ht1632_cs[chipno], HIGH );
+#endif
+    ht1632_cs[chipno] = HIGH;
+//ht1632_cs4 = HIGH;
+}
+
+/*
+ * writebits
+ * Write bits to h1632 on pins HT1632_DATA, HT1632_WRCLK
+ * Chip is assumed to already be chip-selected
+ * Bits are shifted out from MSB to LSB, with the first bit sent
+ * being (bits & firstbit), shifted till firsbit is zero.
+ */
+void HT1632_LedMatrix::writebits (uint8_t bits, uint8_t firstbit)
+{
+  while (firstbit) {
+#ifdef DIRECTIO
+//    output_low(HT1632_WRCLK_PORT, HT1632_WRCLK);
+#else
+//    digitalWrite( HT1632_WRCLK, LOW );
+#endif
+    ht1632_wrclk = LOW;
+    if (bits & firstbit) {
+#ifdef DIRECTIO
+//      output_high(HT1632_DATA_PORT,HT1632_DATA);
+#else
+//    digitalWrite( HT1632_DATA, HIGH);
+#endif
+        ht1632_data = HIGH;
+    } else {
+#ifdef DIRECTIO
+//      output_low(HT1632_DATA_PORT, HT1632_DATA);
+#else
+//    digitalWrite( HT1632_DATA, LOW);
+#endif
+        ht1632_data = LOW;
+    }
+#ifdef DIRECTIO
+//    output_high(HT1632_WRCLK_PORT, HT1632_WRCLK);
+#else
+//    digitalWrite( HT1632_WRCLK, HIGH);
+#endif
+    ht1632_wrclk = HIGH;
+    firstbit >>= 1;
+  }
+}
+
+/*
+ * writedatabits
+ * Write databits to h1632 on pins HT1632_DATA, HT1632_WRCLK
+ * Chip is assumed to already be chip-selected
+ * Bits are shifted out from LSB to MSB
+ */
+void HT1632_LedMatrix::writedatabits (uint8_t bits, uint8_t count)
+{
+  while (count) {
+//    output_low(HT1632_WRCLK_PORT, HT1632_WRCLK);
+    ht1632_wrclk = LOW;
+    if (bits & 1) {
+//      output_high(HT1632_DATA_PORT,HT1632_DATA);
+        ht1632_data = HIGH;
+    } else {
+//      output_low(HT1632_DATA_PORT, HT1632_DATA);
+        ht1632_data = LOW;
+    }
+//    output_high(HT1632_WRCLK_PORT, HT1632_WRCLK);
+    ht1632_wrclk = HIGH;
+    count--;
+    bits >>= 1;
+  }
+}
+
+/*
+ * sendcmd
+ * Send a command to the ht1632 chip.
+ * A command consists of a 3-bit "CMD" ID, an 8bit command, and
+ * one "don't care bit".
+ *   Select 1 0 0 c7 c6 c5 c4 c3 c2 c1 c0 xx Free
+ */
+void HT1632_LedMatrix::sendcmd (uint8_t chipno, uint8_t command)
+{
+  chipselect(chipno);  // Select chip
+  writebits(HT1632_ID_CMD, 0x04);   //1<<2);  // send 3 bits of id: COMMMAND
+  writebits(command, 0x80); //1<<7);  // send the actual command
+  writebits(0, 1);  /* one extra dont-care bit in commands. */
+  chipfree(chipno); //done
+}
+
+/*
+ * clear
+ * clear the display, and the shadow memory, and the snapshot
+ * memory.  This uses the "write multiple words" capability of
+ * the chipset by writing all 96 words of memory without raising
+ * the chipselect signal.
+ */
+void HT1632_LedMatrix::clear()
+{
+  char i;
+
+  for (uint8_t chipno=0; chipno<numDevices; chipno++){
+    chipselect(chipno);  // Select chip
+    writebits(HT1632_ID_WR, 0x04);  //1<<2);  // send ID: WRITE to RAM
+    writebits(0, 0x40);     //1<<6); // Send address
+    for (i = 0; i < 32; i++) // Clear entire display
+      writedatabits(0, 8);  //1<<7); // send 8 bits of data
+    chipfree(chipno); // done
+    for (i=0; i < 64; i++)
+      shadowram[i+64*chipno] = 0;
+  }
+  cursorX = 0;
+  cursorY = 0;
+}
+
+
+// Brighness is from 0 to 15
+void HT1632_LedMatrix::setBrightness( unsigned char brightness ) {
+  for (uint8_t chipno=0; chipno<numDevices; chipno++) {
+    sendcmd(chipno, HT1632_CMD_PWM | (brightness & 0x0F ));
+  }
+}
+
+
+/*
+ * senddata
+ * send a nibble (4 bits) of data to a particular memory location of the
+ * ht1632.  The command has 3 bit ID, 7 bits of address, and 4 bits of data.
+ *    Select 1 0 1 A6 A5 A4 A3 A2 A1 A0 D0 D1 D2 D3 Free
+ * Note that the address is sent MSB first, while the data is sent LSB first!
+ * This means that somewhere a bit reversal will have to be done to get
+ * zero-based addressing of words and dots within words.
+ */
+void HT1632_LedMatrix::senddata (uint8_t chipno, uint8_t address, uint8_t data)
+{
+  chipselect(chipno);  // Select chip
+  writebits(HT1632_ID_WR, 0x04);    //1<<2);  // send ID: WRITE to RAM
+  writebits(address, 0x40);     //1<<6); // Send address
+  writedatabits(data, 4);       //1<<3); // send 4 bits of data
+  chipfree(chipno); // done
+}
+
+/*
+ * sendcol
+ * send a byte of data to a particular memory location of the
+ * ht1632.  The command has 3 bit ID, 7 bits of address, and 8 bits of data.
+ *    Select 1 0 1 A6 A5 A4 A3 A2 A1 A0 D0 D1 D2 D3 D4 D5 D6 D7 D8 Free
+ * Note that the address is sent MSB first, while the data is sent LSB first!
+ * This means that somewhere a bit reversal will have to be done to get
+ * zero-based addressing of words and dots within words.
+ */
+void HT1632_LedMatrix::sendcol (uint8_t chipno, uint8_t address, uint8_t data)
+{
+  chipselect(chipno);  // Select chip
+  writebits(HT1632_ID_WR, 0x04);    //1<<2);  // send ID: WRITE to RAM
+  writebits(address, 0x40);     //1<<6); // Send address
+  writedatabits(data, 8);       // send 8 bits of data
+  chipfree(chipno); // done
+}
+
+// Write a string at the position specified
+void HT1632_LedMatrix::putString(int x, int y, char *str) {
+    cursorX = x;
+    cursorY = y;
+    while( *str ) {
+        putChar( cursorX, y, *str++ );
+        cursorX += 6;
+    }
+}
+
+/*
+ * Copy a character glyph from the smallFont data structure to
+ * display memory, with its upper left at the given coordinate
+ * This is unoptimized and simply uses plot() to draw each dot.
+ */
+void HT1632_LedMatrix::write( uint8_t c) {
+    putChar( cursorX, cursorY, (char)c );   
+}
+
+/*
+ * Copy a character glyph from the myfont data structure to
+ * display memory, with its upper left at the given coordinate
+ * This is unoptimized and simply uses plot() to draw each dot.
+ * returns number of columns that didn't fit
+ */
+uint8_t HT1632_LedMatrix::putChar(int x, int y, char c) {
+  // fonts defined for ascii 32 and beyond (index 0 in font array is ascii 32);
+  // CGRAM characters are in range 0 to 15 with 8-15 being repeat of 0-7
+  // note we force y to be modulo 8 - we do not support writing character to partial y values.
+
+  uint8_t charIndex;
+  uint8_t colData;
+  uint8_t numCols;
+  uint8_t chipno;
+  uint8_t addr;
+  uint8_t colsLeft = 0;        // cols that didn't fit
+
+  if( c > 15 ) {
+    // Regular characters
+    // replace undisplayable characters with blank;
+    if (c < 32 || c > 126) {
+            charIndex = 0;
+    } else {
+            charIndex = c - 32;
+    }
+
+    // move character definition, pixel by pixel, onto the display;
+    // fonts are defined as one byte per col;
+    numCols=smallFont[charIndex][6];   // get the number of columns this character uses
+    for (uint8_t col=0; col<numCols; col++) {
+            colData = smallFont[charIndex][col];
+        chipno = chip_number(x,y);
+        addr = chip_byte_address(x,y); // compute which memory byte this is in
+        if (x <= xMax && y <= yMax) {
+            shadowram[(addr>>1)+32*chipno] = colData;
+            sendcol(chipno,addr,colData);
+            x++;
+        } else {
+            colsLeft++;
+        }
+    }
+  } else {
+    // CGRAM Characters
+    charIndex = c & 0x07;       // Only low 3 bits count
+    numCols=cgram[charIndex][0];    // get the number of columns this character uses
+    // fonts are defined as one byte per col;
+        for (uint8_t col=1; col<=numCols; col++) {
+            colData = cgram[charIndex][col];
+        chipno = chip_number(x,y);
+        addr = chip_byte_address(x,y); // compute which memory byte this is in
+        if (x <= xMax && y <= yMax) {
+            shadowram[(addr>>1)+32*chipno] = colData;
+            sendcol(chipno,addr,colData);
+            x++;
+        } else {
+            colsLeft++;
+        }
+    }
+  }
+
+  cursorX = x;
+  cursorY = y;
+
+  return colsLeft;
+}
+
+// Set position of cursor for writing
+void HT1632_LedMatrix::gotoXY(int x, int y) {
+    cursorX = x;
+    cursorY = y;
+}
+
+void HT1632_LedMatrix::getXY(int* x, int* y)
+{
+    *x = cursorX;
+    *y = cursorY;
+}
+
+void HT1632_LedMatrix::getXYMax(int* x, int* y)
+{
+    *x = xMax;
+    *y = yMax;
+}
+
+// Shift cursor X position a number of positions either left or right.
+void HT1632_LedMatrix::shiftCursorX(int xinc) {
+    cursorX += xinc;
+}
+
+
+/*
+ * plot a point on the display, with the upper left hand corner
+ * being (0,0), and the lower right hand corner being (xMax-1, yMax-1).
+ * Note that Y increases going "downward" in contrast with most
+ * mathematical coordiate systems, but in common with many displays
+ * basic bounds checking used.
+ */
+void HT1632_LedMatrix::plot (int x, int y, char val)
+{
+  if (x<0 || x>xMax || y<0 || y>yMax)
+     return;
+
+  uint8_t chipno = chip_number(x,y);
+  char addr = chip_byte_address(x,y); // compute which memory word this is in
+  char shadowAddress = addr >>1;
+
+  char bitval = 1<<(y&7);  // compute which bit will need set
+
+
+  if (val) {  // Modify the shadow memory
+    shadowram[shadowAddress +32*chipno] |= bitval;
+  }
+  else {
+    shadowram[shadowAddress +32*chipno] &= ~bitval;
+  }
+  // Now copy the new memory value to the display
+  sendcol(chipno, addr, shadowram[shadowAddress +32*chipno]);
+}
+
+
+void HT1632_LedMatrix::setCustomChar( int charNum, unsigned char cgchar[] ) {
+    for(int i=1; i<7; i++ ) {
+        cgram[charNum][i] = (uint8_t)cgchar[i];
+    }
+    cgram[charNum][6] = 0;
+    cgram[charNum][0] = 6;
+}
+
+void HT1632_LedMatrix::setCustomChar( int charNum, unsigned char cgchar[], uint8_t numCols ) {
+    numCols = max(numCols, 6 );
+    for(int i=1; i<=numCols; i++ ) {
+        cgram[charNum][i] = (uint8_t)cgchar[i];
+    }
+    cgram[charNum][0] = numCols;
+    cgram[charNum][numCols] = 0;
+}
+
+void HT1632_LedMatrix::scrollLeft(uint8_t numberCols)
+{
+    for (int i=0; i<128-numberCols-1; i++)
+    {
+        shadowram[i]=shadowram[i+numberCols];
+    }
+    for (int i=128-numberCols; i<128; i++)
+    {
+        shadowram[i]=0;
+    }
+    cursorX -= numberCols;
+    if (cursorX < 0 ) cursorX = 0;
+}
+
+void HT1632_LedMatrix::putShadowRam()
+{
+    for (int chipno=0; chipno<numDevices; chipno++)
+        putShadowRam(chipno);
+}
+
+void HT1632_LedMatrix::putShadowRam(uint8_t chipno)
+{
+    for (int i=0; i<64; i+=2)
+    {
+        sendcol(chipno,i,shadowram[(i>>1)+32*chipno]);
+    }
+}
+
+#ifdef USE_GRAPHIC
+/*
+ * Name         : drawLine
+ * Description  : Draws a line between two points on the display.
+ * Argument(s)  : x1, y1 - Absolute pixel coordinates for line origin.
+ *                x2, y2 - Absolute pixel coordinates for line end.
+ *                c - either PIXEL_ON, PIXEL_OFF
+ * Return value : none
+ */
+void HT1632_LedMatrix::drawLine(unsigned char x1, unsigned char y1,
+        unsigned char x2, unsigned char y2, unsigned char c) {
+    int dx, dy, stepx, stepy, fraction;
+
+    /* Calculate differential form */
+    /* dy   y2 - y1 */
+    /* -- = ------- */
+    /* dx   x2 - x1 */
+
+    /* Take differences */
+    dy = y2 - y1;
+    dx = x2 - x1;
+
+    /* dy is negative */
+    if ( dy < 0 ) {
+        dy    = -dy;
+        stepy = -1;
+    } else {
+        stepy = 1;
+    }
+
+    /* dx is negative */
+    if ( dx < 0 ) {
+        dx    = -dx;
+        stepx = -1;
+    } else {
+        stepx = 1;
+    }
+
+    dx <<= 1;
+    dy <<= 1;
+
+    /* Draw initial position */
+    plot( x1, y1, c );
+
+    /* Draw next positions until end */
+    if ( dx > dy ) {
+        /* Take fraction */
+        fraction = dy - ( dx >> 1);
+        while ( x1 != x2 ) {
+            if ( fraction >= 0 ) {
+                y1 += stepy;
+                fraction -= dx;
+            }
+            x1 += stepx;
+            fraction += dy;
+
+            /* Draw calculated point */
+            plot( x1, y1, c );
+        }
+    } else {
+        /* Take fraction */
+        fraction = dx - ( dy >> 1);
+        while ( y1 != y2 ) {
+            if ( fraction >= 0 ) {
+                x1 += stepx;
+                fraction -= dy;
+            }
+            y1 += stepy;
+            fraction += dx;
+
+            /* Draw calculated point */
+            plot( x1, y1, c );
+        }
+    }
+}
+
+
+/*
+ * Name         : drawRectangle
+ * Description  : Draw a rectangle given to top left and bottom right points
+ * Argument(s)  : x1, y1 - Absolute pixel coordinates for top left corner
+ *                x2, y2 - Absolute pixel coordinates for bottom right corner
+ *                c - either PIXEL_ON, PIXEL_OFF 
+ * Return value : none
+ */
+void HT1632_LedMatrix::drawRectangle(unsigned char x1, unsigned char y1,
+        unsigned char x2, unsigned char y2, unsigned char c){
+    drawLine( x1, y1, x2, y1, c );
+    drawLine( x1, y1, x1, y2, c );
+    drawLine( x1, y2, x2, y2, c );
+    drawLine( x2, y1, x2, y2, c );
+}
+
+
+/*
+ * Name         : drawFilledRectangle
+ * Description  : Draw a filled rectangle given to top left and bottom right points
+ *        just simply draws horizontal lines where the rectangle would be
+ * Argument(s)  : x1, y1 - Absolute pixel coordinates for top left corner
+ *                x2, y2 - Absolute pixel coordinates for bottom right corner
+ *                c - either PIXEL_ON, PIXEL_OFF
+ * Return value : none
+ */
+void HT1632_LedMatrix::drawFilledRectangle(unsigned char x1, unsigned char y1,
+        unsigned char x2, unsigned char y2, unsigned char c) {
+    for(int i=y1; i <= y2; i++ ) {
+        drawLine( x1, i, x2, i, c );
+    }
+}
+
+
+/*
+ * Name         : drawCircle
+ * Description  : Draw a circle using Bresenham's algorithm. 
+ *        Some small circles will look like squares!!
+ * Argument(s)  : xc, yc - Centre of circle
+ *        r - Radius
+ *        c - either PIXEL_ON, PIXEL_OFF
+ * Return value : None 
+ */
+void HT1632_LedMatrix::drawCircle(unsigned char xc, unsigned char yc,
+        unsigned char r, unsigned char c) {
+    int x=0;
+    int y=r;
+    int p=3-(2*r);
+
+        plot( xc+x,yc-y, c);
+
+    for(x=0;x<=y;x++) {
+        if (p<0) {
+            y=y;
+            p=(p+(4*x)+6);
+        } else {
+            y=y-1;
+            p=p+((4*(x-y)+10));
+        }
+
+        plot(xc+x,yc-y, c);
+        plot(xc-x,yc-y, c);
+        plot(xc+x,yc+y, c);
+        plot(xc-x,yc+y, c);
+        plot(xc+y,yc-x, c);
+        plot(xc-y,yc-x, c);
+        plot(xc+y,yc+x, c);
+        plot(xc-y,yc+x, c);
+    }
+}
+#endif
+
+// The end!
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HT1632_LedMatrix.h	Thu Nov 08 21:41:33 2012 +0000
@@ -0,0 +1,87 @@
+/*
+*   HT1632_LedMatrix.h
+*   defintions for Holtek ht1632 LED driver
+*/
+
+#ifndef _HT1632_LEDMATRIX_H
+#define _HT1632_LEDMATRIX_H
+
+#define USE_GRAPHIC
+
+
+#include <inttypes.h>
+
+/*
+ * commands written to the chip consist of a 3 bit "ID", followed by
+ * either 9 bits of "Command code" or 7 bits of address + 4 bits of data.
+ */
+#define HT1632_ID_CMD 4     /* ID = 100 - Commands */
+#define HT1632_ID_RD  6     /* ID = 110 - Read RAM */
+#define HT1632_ID_WR  5     /* ID = 101 - Write RAM */
+
+#define HT1632_CMD_SYSDIS 0x00  /* CMD= 0000-0000-x Turn off oscil */
+#define HT1632_CMD_SYSON  0x01  /* CMD= 0000-0001-x Enable system oscil */
+#define HT1632_CMD_LEDOFF 0x02  /* CMD= 0000-0010-x LED duty cycle gen off */
+#define HT1632_CMD_LEDON  0x03  /* CMD= 0000-0011-x LEDs ON */
+#define HT1632_CMD_BLOFF  0x08  /* CMD= 0000-1000-x Blink ON */
+#define HT1632_CMD_BLON   0x09  /* CMD= 0000-1001-x Blink Off */
+#define HT1632_CMD_SLVMD  0x10  /* CMD= 0001-00xx-x Slave Mode */
+#define HT1632_CMD_MSTMD  0x14  /* CMD= 0001-01xx-x Master Mode */
+#define HT1632_CMD_RCCLK  0x18  /* CMD= 0001-10xx-x Use on-chip clock */
+#define HT1632_CMD_EXTCLK 0x1C  /* CMD= 0001-11xx-x Use external clock */
+#define HT1632_CMD_COMS00 0x20  /* CMD= 0010-ABxx-x commons options */
+#define HT1632_CMD_COMS01 0x24  /* CMD= 0010-ABxx-x commons options */
+#define HT1632_CMD_COMS10 0x28  /* CMD= 0010-ABxx-x commons options */
+#define HT1632_CMD_COMS11 0x2C  /* CMD= 0010-ABxx-x commons options */
+#define HT1632_CMD_PWM    0xA0  /* CMD= 101x-PPPP-x PWM duty cycle */
+
+#define PIXEL_OFF 0
+#define PIXEL_ON  1
+
+//class HT1632_LedMatrix 
+class HT1632_LedMatrix  //: public Print 
+{
+  private:
+    void chipselect( uint8_t );
+    void chipfree( uint8_t );
+    void writebits( uint8_t, uint8_t );
+    void writedatabits( uint8_t, uint8_t );
+    void sendcmd( uint8_t, uint8_t );
+    void senddata( uint8_t, uint8_t, uint8_t );
+    void sendcol( uint8_t, uint8_t, uint8_t );
+
+  public:
+    HT1632_LedMatrix( );
+    
+    // Init/Clear/position functions
+    void init( uint8_t, uint8_t );
+    void clear(void);
+    void setBrightness( unsigned char );
+    uint8_t putChar( int, int, char );
+    void write( uint8_t );
+    void putString( int, int, char* );
+    void plot( int, int, char );
+    void gotoXY(int , int);
+    void getXY(int* , int*);
+    void getXYMax(int*, int*);
+    void shiftCursorX(int );
+    void setCustomChar( int, unsigned char[]);
+    void setCustomChar( int, unsigned char[], uint8_t );
+    void scrollLeft(uint8_t);
+    void putShadowRam();
+    void putShadowRam(uint8_t);
+    // Graphic functions
+#ifdef  USE_GRAPHIC
+    void drawLine(unsigned char x1, unsigned char y1,
+            unsigned char x2, unsigned char y2, unsigned char c);
+    void drawRectangle(unsigned char x1, unsigned char y1,
+            unsigned char x2, unsigned char y2, unsigned char c);
+    void drawFilledRectangle(unsigned char x1, unsigned char y1,
+            unsigned char x2, unsigned char y2, unsigned char c);
+    void drawCircle(unsigned char xc, unsigned char yc,
+            unsigned char r, unsigned char c);
+#endif
+
+};
+
+#endif //_HT1632_LEDMATRIX_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/font_5x7_p.h	Thu Nov 08 21:41:33 2012 +0000
@@ -0,0 +1,103 @@
+// Font definition for LCD 3110 library
+// 5 x 7 font
+// 1 pixel space at left and bottom
+// index = ASCII - 32
+//#include <avr/pgmspace.h>
+
+//***** Small fonts (5x7) **********
+
+static const unsigned char smallFont[][7] =
+{
+      {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 4} ,   // sp
+      {0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 2} ,   // !
+      {0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 4} ,   // "
+      {0x14, 0x3e, 0x14, 0x3e, 0x14, 0x00, 6} ,   // #
+      {0x24, 0x2a, 0x7f, 0x2a, 0x12, 0x00, 6} ,   // $
+      {0x23, 0x13, 0x08, 0x64, 0x62, 0x00, 6} ,   // %
+      {0x36, 0x49, 0x56, 0x20, 0x50, 0x00, 6} ,   // &
+      {0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 2} ,   // '
+      {0x1c, 0x22, 0x41, 0x00, 0x00, 0x00, 4} ,   // (
+      {0x41, 0x22, 0x1c, 0x00, 0x00, 0x00, 4} ,   // )
+      {0x2a, 0x1c, 0x7f, 0x1c, 0x2a, 0x00, 6} ,   // *
+      {0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 6} ,   // +
+      {0x50, 0x30, 0x00, 0x00, 0x00, 0x00, 3} ,   // , 
+      {0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 6} ,   // -
+      {0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 3} ,   // .
+      {0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 6} ,   // /
+      {0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 6} ,   // 0
+      {0x42, 0x7F, 0x40, 0x00, 0x00, 0x00, 4} ,   // 1
+      {0x42, 0x61, 0x51, 0x49, 0x46, 0x00, 6} ,   // 2
+      {0x22, 0x41, 0x49, 0x49, 0x36, 0x00, 6} ,   // 3
+      {0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, 6} ,   // 4
+      {0x27, 0x45, 0x45, 0x45, 0x39, 0x00, 6} ,   // 5
+      {0x3C, 0x4A, 0x49, 0x49, 0x30, 0x00, 6} ,   // 6
+      {0x01, 0x71, 0x09, 0x05, 0x03, 0x00, 6} ,   // 7
+      {0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 6} ,   // 8
+      {0x06, 0x49, 0x49, 0x49, 0x3E, 0x00, 6} ,   // 9
+      {0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 3} ,   // :
+      {0x56, 0x36, 0x00, 0x00, 0x00, 0x00, 3} ,   // ;
+      {0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 5} ,   // <
+      {0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 6} ,   // =
+      {0x41, 0x22, 0x14, 0x08, 0x00, 0x00, 5} ,   // >
+      {0x02, 0x01, 0x51, 0x09, 0x06, 0x00, 6} ,   // ?
+      {0x3e, 0x41, 0x5d, 0x55, 0x5E, 0x00, 6} ,   // @
+      {0x7c, 0x12, 0x11, 0x12, 0x7c, 0x00, 6} ,   // A
+      {0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, 6} ,   // B
+      {0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, 6} ,   // C
+      {0x7F, 0x41, 0x41, 0x41, 0x3e, 0x00, 6} ,   // D
+      {0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, 6} ,   // E
+      {0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, 6} ,   // F
+      {0x3E, 0x41, 0x49, 0x49, 0x3A, 0x00, 6} ,   // G
+      {0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 6} ,   // H
+      {0x41, 0x7F, 0x41, 0x00, 0x00, 0x00, 4} ,   // I
+      {0x20, 0x40, 0x40, 0x3F, 0x00, 0x00, 5} ,   // J
+      {0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, 6} ,   // K
+      {0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, 6} ,   // L
+      {0x7F, 0x02, 0x0C, 0x02, 0x7F, 0x00, 6} ,   // M
+      {0x7F, 0x02, 0x04, 0x08, 0x7F, 0x00, 6} ,   // N
+      {0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, 6} ,   // O
+      {0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, 6} ,   // P
+      {0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, 6} ,   // Q
+      {0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, 6} ,   // R
+      {0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 6} ,   // S
+      {0x01, 0x01, 0x7F, 0x01, 0x01, 0x00, 6} ,   // T
+      {0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, 6} ,   // U
+      {0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, 6} ,   // V
+      {0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, 6} ,   // W
+      {0x63, 0x14, 0x08, 0x14, 0x63, 0x00, 6} ,   // X
+      {0x07, 0x08, 0x70, 0x08, 0x07, 0x00, 6} ,   // Y
+      {0x61, 0x51, 0x49, 0x45, 0x43, 0x00, 6} ,   // Z
+      {0x7F, 0x41, 0x41, 0x00, 0x00, 0x00, 4} ,   // [
+      {0x55, 0x2A, 0x55, 0x2A, 0x55, 0x00, 6} ,   // Chequer
+      {0x41, 0x41, 0x7F, 0x00, 0x00, 0x00, 4} ,   // ]
+      {0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 6} ,   // ^
+      {0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 6} ,   // _
+      {0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 4} ,   // '
+      {0x20, 0x54, 0x54, 0x78, 0x00, 0x00, 5} ,   // a
+      {0x7F, 0x44, 0x44, 0x38, 0x00, 0x00, 5} ,   // b
+      {0x38, 0x44, 0x44, 0x44, 0x00, 0x00, 5} ,   // c
+      {0x38, 0x44, 0x44, 0x7F, 0x00, 0x00, 5} ,   // d
+      {0x38, 0x54, 0x54, 0x58, 0x00, 0x00, 5} ,   // e
+      {0x04, 0x7E, 0x05, 0x01, 0x00, 0x00, 5} ,   // f
+      {0x48, 0x54, 0x54, 0x3c, 0x00, 0x00, 5} ,   // g
+      {0x7F, 0x08, 0x04, 0x78, 0x00, 0x00, 5} ,   // h
+      {0x7D, 0x00, 0x00, 0x00, 0x00, 0x00, 2} ,   // i
+      {0x20, 0x40, 0x3D, 0x00, 0x00, 0x00, 4} ,   // j
+      {0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 5} ,   // k
+      {0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 2} ,   // l
+      {0x78, 0x04, 0x18, 0x04, 0x78, 0x00, 6} ,   // m
+      {0x7c, 0x08, 0x04, 0x78, 0x00, 0x00, 5} ,   // n
+      {0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 5} ,   // o
+      {0x7C, 0x14, 0x14, 0x08, 0x00, 0x00, 5} ,   // p
+      {0x08, 0x14, 0x14, 0x7C, 0x00, 0x00, 5} ,   // q
+      {0x7C, 0x08, 0x04, 0x04, 0x00, 0x00, 5} ,   // r
+      {0x48, 0x54, 0x54, 0x24, 0x00, 0x00, 5} ,   // s
+      {0x04, 0x7F, 0x44, 0x00, 0x00, 0x00, 4} ,   // t
+      {0x3C, 0x40, 0x40, 0x3c, 0x00, 0x00, 5} ,   // u
+      {0x0C, 0x30, 0x40, 0x30, 0x0c, 0x00, 6} ,   // v
+      {0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, 6} ,   // w
+      {0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 6} ,   // x
+      {0x0C, 0x50, 0x50, 0x3c, 0x00, 0x00, 5} ,   // y
+      {0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 6} ,   // z
+      {0x06, 0x09, 0x09, 0x06, 0x00, 0x00, 5}     // degree
+};