I was able, eventually, to get all of your code to compile. I changed all the .c files to .cpp. Whether that was needed, or not, I'm not sure. It looked like it was needed when I did it.
Every single file needed to be changed. The most significant change was to change all the & arguments to * arguments.
Here's the custom_types.h file that I ended up with:
#ifndef CUSTOM_TYPES_H
#define CUSTOM_TYPES_H
#include "WProgram.h"
//Matrix
const int pinMap[] = {13,12,6,8,11,7,5,10,4,9,2};
#define numChannels 11
//PWM
const int frequency = 512;
const int minDuty = 0;
const int maxDuty = 256;
const int period = 2;
const int ON = HIGH;
const int OFF = LOW;
struct _PWM
{
int duty;
int state;
long lastUpdate;
int updateInterval;
int onInterval;
int offInterval;
};
typedef struct _PWM PWM;
void initPWM(PWM *pwm);
boolean updatePWM(PWM *pwm);
struct _Channel
{
int pin;
int color;
int state;
boolean dirty;
PWM *pwm;
};
typedef struct _Channel Channel;
void initChannel(Channel *chan);
void updateChannel(Channel *chan);
struct _Matrix
{
int width;
Channel *chan[numChannels];
};
typedef struct _Matrix Matrix;
void initMatrix(Matrix *matrix);
void updateMatrix(Matrix *matrix);
void runMode(Matrix *matrix);
void changeMode();
void render(Matrix *matrix);
void Tide(Channel *matrix[]);
void Knight(Channel *matrix[]);
#endif
The sketch:
#include "custom_types.h"
#include <EEPROM.h>
Matrix matrix;
void setup()
{
//Visit the Matrix tab to
//set the pin mapping.
initMatrix(&matrix);
changeMode();
}
void loop()
{
//Visit the mode tab for
//instructions on programming modes.
runMode(&matrix);
updateMatrix(&matrix);
render(&matrix);
}
The PWM.cpp file:
#include "custom_types.h"
void initPWM(PWM *pwm)
{
pwm->duty = maxDuty;
pwm->state = OFF;
pwm->lastUpdate = 0;
pwm->updateInterval = 0;
}
boolean updatePWM(PWM *pwm)
{
long now = millis();
if (now - pwm->lastUpdate > pwm->updateInterval){
pwm->lastUpdate = now;
pwm->onInterval = pwm->duty * period;
pwm->offInterval = frequency - pwm->onInterval;
if (pwm->state == ON)
{
pwm->updateInterval = pwm->offInterval;
return true;
}
else if (pwm->state == OFF)
{
pwm->updateInterval = pwm->onInterval;
return true;
}
else
return false;
}
}
The channel.cpp file:
#include "custom_types.h"
void initChannel(Channel *chan)
{
chan->state = OFF;
chan->dirty = 1;
initPWM(chan->pwm);
}
void updateChannel(Channel *chan)
{
if (chan->state == ON)
{
//Set dirty flag to signal a need for digitalWrite() :)
PWM *pwm = chan->pwm;
boolean stat = updatePWM(pwm);
chan->dirty = stat;
}
}
The matrix.cpp file:
#include "custom_types.h"
void initMatrix(Matrix *matrix)
{
/*
This function should be called in setup()
*/
matrix->width = numChannels;
for (int i=0; i<matrix->width; i++)
{
matrix->chan[i]->pin = pinMap[i];
pinMode(matrix->chan[i]->pin, OUTPUT);
}
}
void updateMatrix(Matrix *matrix)
{
for (int i=0; i < matrix->width; i++)
{
updateChannel(matrix->chan[i]);
}
}
The modes.cpp file:
#include "custom_types.h"
const int TIDE = 0;
const int KNIGHT = 1;
const int PULSE = 2;
const int NUM_MODES = 3;
int mode;
int forward = true;
void runMode(Matrix *matrix)
{
switch (mode)
{
case TIDE:
Tide(matrix->chan);
break;
case KNIGHT:
Knight(matrix->chan);
break;
}
}
#include <EEPROM.h>
void changeMode()
{
int address = 0;
mode = EEPROM.read(address);
EEPROM.write(address, (byte)((mode+1) % NUM_MODES) );
}
//Modes ===========================================================
//Tide() turns the leds on in sequence. They turn on one by one until every
//LED is on. then they turn off in the same order.
void Tide(Channel *matrix[])
{
int ledCount = 3;
if (forward)
{
for (int i=0; i<ledCount; i++)
{
if (matrix[i]->state == LOW)
{
matrix[i]->state = HIGH;
if (i+1 == ledCount) {forward = false;}
return;
}
}
}
else
{ //go backwards
for (int i = ledCount-1; i > -1; i--)
{
if (matrix[i]->state == HIGH)
{
matrix[i]->state = LOW;
if(i == 0) {forward = true;}
return;
}
}
}
}
//Almost exactly like Tide(), except only one LED is on at a time.
//It looks like the car KITT from KNIGHT RIDER.
void Knight(Channel *matrix[])
{
int ledCount = 3;
if (forward)
{
for (int i=0; i<ledCount; i++)
{
if (matrix[i]->state == LOW)
{
matrix[i]->state = HIGH;
if (i>0) { matrix[i-1]->state = LOW; }
if (i+1 == ledCount){ forward = false; }
return;
}
}
}
else
{ //go backwards
for (int i = ledCount-1 ; i > -1; i--)
{
if (matrix[i]->state == HIGH)
{
matrix[i]->state = LOW;
if (i < ledCount-1) {matrix[i+1]->state = LOW; }
if(i == 0){ forward = true; }
return;
}
}
}
}
The ledCount variable was not defined anywhere. I stuck something in there to get this function to compile. Probably should be defined in custom_types.h (as const).
Finally, render.cpp:
#include "custom_types.h"
void render(Matrix *matrix)
{
/*
Similar to how a video game separates logic and rendering,
We'll calculate the matrix state and apply PWM effects
before pushing out whether the pins are high or low.
We even track which chans are 'dirty.'
Passing by reference for speed, not sure if that really
needs to be done, but I figured it was a couple hundred bytes
per cycle that don't need to be copied :p
*/
for (int i=0; i < matrix->width; i++)
{
if (matrix->chan[i]->dirty)
{
digitalWrite(matrix->chan[i]->pin, matrix->chan[i]->state);
}
}
}
I don't have your hardware, so I have no idea if this executes properly, but it does compile and link.