Skip to content

Instantly share code, notes, and snippets.

@robotjoosen
Created October 10, 2012 19:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robotjoosen/3868021 to your computer and use it in GitHub Desktop.
Save robotjoosen/3868021 to your computer and use it in GitHub Desktop.
Veins 74HC595 PWM code
/* ------------------------------------------------------------------------------------------------
* Cynaptic Collective - Veins Basic v1.0
*
* Project : Veins
* Client : Melkweg Amsterdam / OffCentre 2012 / Deframe Collective
* Author : Roald Joosen
* Start date : 21 aug 2012
* End date : 16 sept 2012
*
* ------------------------------------------------------------------------------------------------ */
// Include Libraries
#include <TimerOne.h>
// 74HC595 Settings
#define shiftRegisters 4 // Shift Register Amount
byte setRegisterPin[shiftRegisters * 8]; // Pin total
int __74HC595_DS = 11; // Serial Data Input
int __74HC595_SH_CP = 13; // Shift Register Clock pin
int __74HC595_ST_CP = 10; // Storage Register Clock pin (latch pin)
int __74HC595_ST_CP_PORTB = __74HC595_ST_CP - 8; // Faster Latch
// Segment Mask
int layout_cols = 19;
int layout_rows = 3;
int layout[3][19] =
{
{ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0 }
};
// Pin Assignment
int register_pin_total = 29;
int register_pins [3][19] =
{
{ 0, 1, 2, 3, 6, 9, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 4, 7, 10, 13, 15, 16, 17, 18, 19, 20, 22, 24, 0, 0, 0, 0 },
{ 0, 0, 0, 5, 8, 11, 14, 0, 0, 0, 0, 0, 21, 23, 25, 26, 0, 0, 0 }
};
int register_pin_value[3][3][19]; // [ target value, current value, direction ][ row 1 ~ 3 ][ Segment 0 ~ 19 ]
int max_brightness = 255;
// Timers
unsigned long next_update;
int update_rate;
unsigned long next_segment;
int segment_rate;
int current_segment;
/* ------------------------------------------------------------------------------------------------ */
//
// iProcess && setup SPI
// Original by : Joseph Francis
//
/* ------------------------------------------------------------------------------------------------ */
#define TICKER_PWM_LEVELS 32 // Brightness levels
#define TICKER_STEP 256/TICKER_PWM_LEVELS // Full Step size
#define TICKER_HALFSTEP 256/(TICKER_PWM_LEVELS/2) // Half Step size
#define TICKER_QUADSTEP 256/(TICKER_PWM_LEVELS/4) // Quad Step size
#define TIMER_DELAY 280 // Higher is slower
int ticker;
void iProcess()
{
byte registerValue[shiftRegisters];
ticker = ( ticker > TICKER_PWM_LEVELS ) ? 0 : ticker + 1;
int myPos = ticker * TICKER_STEP;
for (int i = 0 ; i < 8; i++ )
{
int myLev = 0;
for (int iSR = 0 ; iSR < shiftRegisters ; iSR++)
{
myLev = (setRegisterPin[i+(iSR*8)] > myPos) ? 1 : 0;
bitWrite( registerValue[iSR], i, myLev );
}
}
latchOff();
for (int iSR = shiftRegisters-1 ; iSR >= 0 ; iSR--)
{
spi_transfer(registerValue[iSR]);
}
latchOn();
}
void latchOn()
{
bitSet(PORTB,__74HC595_ST_CP_PORTB);
}
void latchOff()
{
bitClear(PORTB,__74HC595_ST_CP_PORTB);
}
void setupSPI()
{
byte clr;
SPCR |= ( (1<<SPE) | (1<<MSTR) ); // enable SPI as master
SPCR &= ~( (1<<SPR1) | (1<<SPR0) ); // clear prescaler bits
clr=SPSR; // clear SPI status reg
clr=SPDR; // clear SPI data reg
SPSR |= (1<<SPI2X); // set prescaler bits
delay(10);
}
byte spi_transfer(byte data)
{
SPDR = data; // Start the transmission
loop_until_bit_is_set(SPSR, SPIF);
return SPDR; // return the received byte, we don't need that
}
/* ------------------------------------------------------------------------------------------------ */
//
// Loop & Setup
//
/* ------------------------------------------------------------------------------------------------ */
void setup()
{
pinMode(__74HC595_DS, OUTPUT);
pinMode(__74HC595_ST_CP, OUTPUT);
pinMode(__74HC595_SH_CP, OUTPUT);
digitalWrite(__74HC595_DS,LOW);
digitalWrite(__74HC595_ST_CP,LOW);
digitalWrite(__74HC595_SH_CP,LOW);
Serial.begin(9600);
setupSPI();
Timer1.initialize(TIMER_DELAY);
Timer1.attachInterrupt(iProcess);
// Set var values
segment_rate = 200;
update_rate = 20;
}
void loop()
{
if( millis() > next_update )
{
for( int c=0;c<layout_cols; c++ )
{
for( int r=0; r<layout_rows; r++)
{
if(layout[r][c] > 0 && register_pin_value[0][r][c] != register_pin_value[1][r][c])
{
setRegisterPin[register_pins[r][c]] = register_pin_value[1][r][c];
if(register_pin_value[2][r][c] == 0)
{
if(register_pin_value[1][r][c] < register_pin_value[0][r][c]-TICKER_HALFSTEP)
register_pin_value[1][r][c] += TICKER_HALFSTEP;
else
register_pin_value[2][r][c] = 1;
}
else
{
if(register_pin_value[1][r][c] > 0)
{
register_pin_value[1][r][c] -= TICKER_STEP;
}
else
{
register_pin_value[0][r][c] = 0;
register_pin_value[1][r][c] = 0;
register_pin_value[2][r][c] = 0;
}
}
}
}
}
next_update = millis() + update_rate;
}
if( millis() > next_segment )
{
for( int r=0; r < layout_rows; r++ )
{
if( layout[r][current_segment] > 0 )
{
register_pin_value[0][r][current_segment] = max_brightness;
}
}
current_segment = ( current_segment < layout_cols ) ? current_segment + 1 : 0 ;
next_segment = millis() + segment_rate;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment