// allows compile time selection of left or right insertion

#include <LedControl.h>
#include <SoftwareSerial.h>

#define F_CPU 16500000L

#define CS_PIN  PB0
#define CLK_PIN PB1
#define DIN_PIN PB2
#define RND_PIN A0

#define SERIAL_TX PB3
#define SERIAL_RX PB5

#define MAX_SEG 1

const byte MAX_ROWS = 4;  // Set graph height
const byte MAX_COLUMNS = 8;
const byte TOTAL_LEDS = MAX_ROWS * MAX_COLUMNS;

#if TOTAL_LEDS > 64
#undef SERIAL_RX
#endif

const byte DISPLAY_BOTTOM_ROW = 7;
const int ANALOG_FULL_SCALE = 1023;

byte rowImage[MAX_ROWS];
int newValue;
byte fullColumns;
byte partialColumn;
bool leftToRight = true;// true = value grows from left to right, false = right to left

// Instantiate software serial for ATTINY85 and set pins
SoftwareSerial mySerial(SERIAL_RX, SERIAL_TX);

// Set up the matrix control pins and maximum number of segments
LedControl matrixLEDDisplay = LedControl(DIN_PIN, CLK_PIN, CS_PIN, MAX_SEG); // MAX7219

void setup() {
  //Serial.begin(115200);
  mySerial.begin(9600);
  matrixLEDDisplay.shutdown(0, false);
  matrixLEDDisplay.setIntensity(0, 7);
  matrixLEDDisplay.clearDisplay(0);
}

void loop() {

  newValue = map(analogRead(A3), 0, ANALOG_FULL_SCALE, 1, TOTAL_LEDS);
  static int lastValue;

  if (newValue != lastValue) {
  clearRows();
  lastValue = newValue;
  fullColumns = newValue / MAX_ROWS;
  partialColumn = newValue % MAX_ROWS;

  if (partialColumn != 0) {
    insertColumn(partialColumn, leftToRight);
  }

  if (fullColumns != 0) {
    for (byte i = 0; i < fullColumns; i++)
    insertColumn(MAX_ROWS, leftToRight);
  }
  sendImage();
  printStuff();
  }
} // end of loop

//
//  Bit shift the values into the image bytes
//
void insertColumn(byte rows, bool leftToRight) {
    for (byte i = 0; i < rows; i++) {
    if (leftToRight) {
      rowImage[i] <<= 1;
      rowImage[i] |= B1;
    }
      else{
        rowImage[i] = rowImage[i] >> 1;
      rowImage[i] |= B10000000;
    }
  }
}

//
// Erase all the bits in the current image
//
void clearRows(void) {
  for (byte i = 0; i < MAX_ROWS; i++) {
    rowImage[i] = 0;
  }
}

//
// Send the image bytes to the display
//
void sendImage(void) {  
  byte k = DISPLAY_BOTTOM_ROW;
  for (byte j = 0; j < MAX_ROWS; j++) {
    matrixLEDDisplay.setRow(0, k--, rowImage[j]);
  }
}

void printStuff() {
  return;
  mySerial.print("change\t");
  mySerial.print(newValue);
  mySerial.print("\t");
  mySerial.print(fullColumns);
  mySerial.print("\t");
  mySerial.println(partialColumn);
}
ATTINY8520PU