LED Array Using AVR Controller

I created an 8x8 LED matrix controlled by a mircocontroller (specifically Atmega8), an 8-bit shift register (HEF4794) and an array of drivers (MIC2981). The problem I have is that the pattern to be displayed is not centered. It needs to be moved to the left by one column and down into two rows. Any help would be greatly appreciated.

I got the idea for this project from here: http://www.instructables.com/id/LED-matrix-using-shift-registers/

/*
 * AVRGCC3.c
 *
 * Created: 4/28/2012 1:39:29 PM
 *  Author: Scott
 */ 

#define F_CPU 12000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "font8x8.h"

#define ShiftPort   PORTC
#define ShiftDDR    DDRC
#define LatchPin    (1 << 0)
#define DataPin     (1 << 1)
#define ClkPin      (1 << 2)
#define OE          (1 << 3)

#define RowPort     PORTD
#define RowDDR      DDRD
#define RowPin0     (1 << 0)
#define RowPin1     (1 << 1)
#define RowPin2     (1 << 2)
#define RowPin3     (1 << 3)
#define RowPin4     (1 << 4)
#define RowPin5     (1 << 5)
#define RowPin6     (1 << 6)
#define RowPin7     (1 << 7)

#define ScrollSpeed 75  //How many milliseconds to pause before shifting columns left

typedef unsigned char u8;
typedef unsigned int u16;

u8 row_track = 0;

volatile u8 row_buffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

void Delay_ms(int cnt)  //Function delays a give number of milliseconds.  Depends on F_CPU being defined
{
  while (cnt-->0) _delay_ms(1);
}   

static inline void InitPorts(void)  //Function used once to initialize the ports
{
  ShiftDDR |= (LatchPin | ClkPin | DataPin | OE);   //Setup shift register control pins
  RowDDR |= (RowPin0 | RowPin1 | RowPin2 | RowPin3 | RowPin4 | RowPin5 | RowPin6 | RowPin7); //Setup row driver pins

  ShiftPort |= OE;
  RowPort |= RowPin0;               //Drive first row and enable shift registers

  ShiftPort |= LatchPin;                //Set latch pin high
  ShiftPort &= ~(ClkPin | DataPin);             //Set ClkPin and DataPin low
}

static inline void InitTimers(void) //Function used once to set up the timer
{
  TCCR1B |= 1<<WGM12 | 1<<CS11 | 1<<CS10;       //Start timer1 in CTC mode with prescaler of 64
  TIMSK |= 1<<OCIE1A;                   //Enable compare match interrupt
  OCR1A = 0x00BB;                   //Set compare value for 1 mSec
  sei();                        //Enable global interrupts
}

void Shift_Int(u8 shiftData)        //Function used to shift in data
{
  ShiftPort &= ~(LatchPin | ClkPin | DataPin);      //All pins low: LatchPin low signals a write operation

  for (char i=0; i<8; i++)
  {
    ShiftPort &= ~ClkPin;               //Set ClkPin low

    if (shiftData & (1<<i)) ShiftPort |= DataPin;       //Set DataPin high if current bit is 1
    else ShiftPort &= ~DataPin;             //Set DataPin low if current bit is 0

    ShiftPort |= ClkPin;                //Set ClkPin high to increment shift register
    ShiftPort &= ~DataPin;              //Set DataPin low to prepare for next write
  }

  ShiftPort |= LatchPin;                //Set LatchPin high to signal end of write operation
  ShiftPort &= ~(ClkPin | DataPin);             //Reset ClkPin and DataPin to low
}

void Write_Char(u8 pattern)     //Function that writes one pattern to the LED Matrix
{
  //Writes a char to the led matrix
  //Patterns come from font8x8[] in progmem (font8x8.h)
  pattern -= 32;                        
  char temp;
  for (char i=0; i<8; i++)              //Read one column of char at a time
  {
    temp = pgm_read_byte((char *)((int)font8x8 + (8 * pattern) + i));   //Get column from progmem
    for (char j=0; j<8; j++)                        //Cycle through each bit in column
    {
      //Write bits to appropriate row_buffer location
      if (temp & (1<<j)) row_buffer[8-j] |= 1<<(8-i);
      else row_buffer[8-j] &= ~(1<<(8-i));
    }
  }
}

int main(void)
{
    InitPorts();
    InitTimers();
    while(1)
    {
        for (char x = 0; x<255; x++)
        {
            Write_Char(x);
            Delay_ms(500);
        }

    }
}

ISR(TIMER1_COMPA_vect)              //Interrupt Service Routine handles the display.
{
  if(++row_track == 8) row_track = 0;       //Row tracking
  Shift_Int(row_buffer[row_track]);     //Shift in data for next row

  ShiftPort &= ~OE;             //Used to prevent ghosting
  if (row_track == 0)               //Shut down high side controller
  {
    RowPort &= ~(1<<7);             //If Row0 is next, shutdown Row7
  }
  else
  {
    RowPort &= ~(1<<(row_track-1));     //Shutdown previous row
  }

  ShiftPort |= LatchPin;            //Latch low side shift registers
  RowPort |= (1<<row_track);            //Drive high side controller
  ShiftPort |= OE;              //Used to prevent ghosting
}
+3
source share
1 answer

Looks like you should just change this code:

  //Write bits to appropriate row_buffer location
  if (temp & (1<<j)) row_buffer[8-j] |= 1<<(8-i);
  else row_buffer[8-j] &= ~(1<<(8-i));

Perhaps this is just an assumption:

  //Write bits to appropriate row_buffer location
  if (temp & (1<<j)) row_buffer[6-j] |= 1<<(7-i);
  else row_buffer[6-j] &= ~(1<<(7-i));

8 - 6 8-7 . , , , , , , , , , .

+2