Skip to content

Instantly share code, notes, and snippets.

@linuxgnuru
Created August 2, 2018 13:16
Show Gist options
  • Save linuxgnuru/6e7e31f72ed7b17a4ed29f97d38f5d3d to your computer and use it in GitHub Desktop.
Save linuxgnuru/6e7e31f72ed7b17a4ed29f97d38f5d3d to your computer and use it in GitHub Desktop.
/*
Makefile:
DEBUG = -O2 -ggdb
CFLAGS = $(DEBUG) -Wall -std=c++11
LIBS = -lwiringPi
CC = g++
SRC = $(PROGNAME).cpp
OBJ = $(SRC:.cpp=.o)
ifeq ($(PREFIX),)
PREFIX := /usr/local
endif
all: clean $(PROGNAME)
$(PROGNAME): $(OBJ)
@$(CC) -o $@ $(OBJ) $(LIBS)
.cpp.o:
@$(CC) -c $(CFLAGS) $< -o $@
clean:
rm -f *.o $(PROGNAME)
install: $(PROGNAME)
sudo install -d $(PREFIX)/bin/
sudo install -m 4755 $(PROGNAME) $(PREFIX)/bin/
*/
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <cstring>
#include <errno.h>
#include <signal.h>
#include <string.h> // for fprintf
#include <wiringPi.h>
#include <wiringPiSPI.h>
using namespace std;
#define CE 0
class RasPiSPI
{
private:
unsigned char *TxBuffer;
int TxBufferIndex;
public:
RasPiSPI();
~RasPiSPI();
void begin() { begin(CE, 1000000); } // default use channel 0 and 1MHz clock speed
void begin(int, int);
void transfer(char);
void endTransfer();
};
RasPiSPI::RasPiSPI()
{
TxBuffer = new unsigned char[1024]; // Buffer for TxData
TxBufferIndex = 0;
}
RasPiSPI::~RasPiSPI() { delete[] TxBuffer; }
void RasPiSPI::begin(int channel, int speed)
{
// Open port for reading and writing
if (wiringPiSPISetup(channel, speed) < 0)
cout << "Failed to open SPI port " << channel << "! Please try with sudo" << endl;
}
void RasPiSPI::transfer(char c)
{
TxBuffer[TxBufferIndex] = c;
TxBufferIndex++;
}
void RasPiSPI::endTransfer()
{
wiringPiSPIDataRW(CE, TxBuffer, TxBufferIndex);
TxBufferIndex = 0;
}
/*
useage:
printf("m: "BYTE_TO_BINARY_PATTERN" "BYTE_TO_BINARY_PATTERN"\n",
BYTE_TO_BINARY(m>>8), BYTE_TO_BINARY(m));
*/
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY(byte) \
(byte & 0x80 ? '1' : '0'), \
(byte & 0x40 ? '1' : '0'), \
(byte & 0x20 ? '1' : '0'), \
(byte & 0x10 ? '1' : '0'), \
(byte & 0x08 ? '1' : '0'), \
(byte & 0x04 ? '1' : '0'), \
(byte & 0x02 ? '1' : '0'), \
(byte & 0x01 ? '1' : '0')
//MAX7219/MAX7221's memory register addresses:
// See Table 2 on page 7 in the Datasheet
const char NoOp = 0x00;
const char Digits[8] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
};
const char DecodeMode = 0x09;
const char Intensity = 0x0A;
const char ScanLimit = 0x0B;
const char ShutDown = 0x0C;
const char DisplayTest = 0x0F;
const char numOfDevices = 4;
unsigned char ledData[4][8] = {
{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }
};
void setup();
void bitWrite(int addr, int col, int row, int b)
{
if (addr < 0 || addr > 3 || col < 0 || col > 7 || row < 0 || row > 7) return;
ledData[addr][col] ^= (-b ^ ledData[addr][col]) & (1 << row);
}
void bitClear(int addr, int col, int row)
{
if (addr < 0 || addr > 3 || col < 0 || col > 7 || row < 0 || row > 7) return;
ledData[addr][col] ^= (0 ^ ledData[addr][col]) & (1 << row);
}
void bitSet(int addr, int col, int row)
{
if (addr < 0 || addr > 3 || col < 0 || col > 7 || row < 0 || row > 7) return;
ledData[addr][col] ^= (-1 ^ ledData[addr][col]) & (1 << row);
}
bool bitRead(int addr, int col, int row)
{
return (ledData[addr][row] >> col) & 0x01;
}
RasPiSPI SPI;
// Writes data to the selected device or does broadcast if device number is 255
void SetData(char adr, char data, char device)
{
// Count from top to bottom because first data which is sent is for the last device in the chain
for (int i = numOfDevices; i > 0; i--)
{
if ((i == device) || (device == 255))
{
SPI.transfer(adr);
SPI.transfer(data);
}
else // if its not the selected device send the noop command
{
SPI.transfer(NoOp);
SPI.transfer(0);
}
}
SPI.endTransfer();
delay(1);
}
// Writes the same data to all devices
void SetData(char adr, char data) { SetData(adr, data, 255); } // write to all devices (255 = Broadcast)
void SetShutDown(char Mode) { SetData(ShutDown, !Mode); }
void SetScanLimit(char Digits) { SetData(ScanLimit, Digits); }
void SetIntensity(char intense) { SetData(Intensity, intense); }
void SetDecodeMode(char Mode) { SetData(DecodeMode, Mode); }
void clearAll() { for (int i = 0; i < 8; i++) SetData(Digits[i], 0b00000000); }
void Draw(int addr, int col, int row, bool b)
{
char mydata = 0x0;
col = abs(col - 7);
bitWrite(addr, col, row, b);
mydata = ledData[addr][col];
SetData(Digits[col], mydata, addr + 1);
}
void doGraph(int addr, int height, int row)
{
if (height == 0)
{
for (int i = 0; i < 8; i++)
{
Draw(addr, i, row, 0);
}
}
else if (height == 8)
{
for (int i = 0; i < 8; i++)
{
Draw(addr, i, row, 1);
}
}
else
{
for (int i = 7; i > -1; i--)
{
Draw(addr, i, row, (i < height));
}
}
}
static void die(int sig);
int main(int argc, char **argv)
{
int addr, col, row;
(void)signal(SIGINT, die);
(void)signal(SIGHUP, die);
(void)signal(SIGTERM, die);
(void)signal(SIGABRT, die);
setup();
clearAll();
if (argc >= 4)
{
for (int i = 1; i < argc; i += 3)
{
addr = atoi(argv[i]) - 1;
col = atoi(argv[i+1]);
row = atoi(argv[i+2]);
doGraph(addr, col, row);
}
}
else
{
cout << "usage: " << argv[0] << " [panel] [row] [column]\n";
return EXIT_FAILURE;
}
return 0;
}
void setup()
{
// The MAX7219 has officially no SPI / Microwire support like the MAX7221 but the
// serial interface is more or less the same like a SPI connection
SPI.begin();
SetDecodeMode(false); // Disable the decode mode because at the moment i dont use 7-Segment displays
SetScanLimit(7); // Set the number of digits; start to count at 0
SetIntensity(5); // Set the intensity between 0 and 15. Attention 0 is not off!
SetShutDown(false); // Disable shutdown mode
clearAll();
}
static void die(int sig)
{
clearAll();
SetShutDown(1);
if (sig != 0 && sig != 2) (void)fprintf(stderr, "caught signal %s\n", strsignal(sig));
if (sig == 2) (void)fprintf(stderr, "Exiting due to Ctrl + C (%s)\n", strsignal(sig));
exit(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment