|
elektrohase source
//============================================================================
//
// Firmware Elektrohase
//
// Processor: Atmel ATmega8
// Clock: 8 MHz (internal oscillator)
// Developer: Thoralt Franz
// Last change: 07.04.2005
//
//============================================================================
//
// Pin allocation:
//
// PB0: --
// PB1: --
// PB2: register clock shift registers
// PB3: data for shift registers (MOSI)
// PB4: -- (MISO)
// PB5: data clock for shift registers (SCK)
// PB6: --
// PB7: --
//
// PC0: --
// PC1: --
// PC2: --
// PC3: --
// PC4: --
// PC5: --
//
// ADC6: --
// ADC7: --
//
// PD0: --
// PD1: --
// PD2: --
// PD3: --
// PD4: --
// PD5: --
// PD6: --
// PD7: --
//
//============================================================================
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
//----------------------------------------------------------------------------
// global #defines
//----------------------------------------------------------------------------
#define TIMER_1_RELOAD -8000
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
//----------------------------------------------------------------------------
// global variables
//----------------------------------------------------------------------------
volatile unsigned int g_uTimer = 0; // global timer
volatile unsigned int g_uTimerRest = 0; // remaining time of pattern
volatile unsigned char g_ucLED[8];
//----------------------------------------------------------------------------
// overflow timer1
//
// -> --
// <- --
//----------------------------------------------------------------------------
SIGNAL(SIG_OVERFLOW1)
{
TCNT1 = TIMER_1_RELOAD; // reload: 1000 µs
g_uTimer++;
if(g_uTimerRest) g_uTimerRest--;
}
//----------------------------------------------------------------------------
// Init_IO
//
// -> --
// <- --
//----------------------------------------------------------------------------
void Init_IO(void)
{
// ports
DDRB = 0x2C; PORTB = 0x00;
DDRC = 0x00; PORTC = 0x00;
DDRD = 0x00; PORTD = 0x00;
// timer1
TCCR1B = 0x01; // prescaler = 1
sbi(TIMSK, TOIE1); // allow overflow interrupt
TCNT1 = TIMER_1_RELOAD; // reload: 1000 µs
// SPI
SPCR = (1<<SPE) | (1<<MSTR); // SPI enable, master
SPSR = (1<<SPI2X); // double speed (4 MHz)
// allow interrupts globally
sei();
}
//----------------------------------------------------------------------------
// SetLED
//
// sends the array g_ucLED via SPI to the shift registers
//
// -> --
// <- --
//----------------------------------------------------------------------------
void SetLED(void)
{
int i;
for(i=0; i<8; i++)
{
SPDR = g_ucLED[7-i];
while(!(SPSR & (1<<SPIF)));
}
// clock the shift registers contents to their outputs
sbi(PORTB, 2); cbi(PORTB, 2);
}
//----------------------------------------------------------------------------
// BufRotateLeft
//
// rotates the LED buffer by a given number of bits to the left. left carry
// comes in at the right side.
//
// -> iCount = number of bits to rotate the buffer
// <- --
//----------------------------------------------------------------------------
void BufRotateLeft(int iCount)
{
int i, j;
unsigned char u1, u2;
for(j=0; j<iCount; j++)
{
// shift buffer by one bit to the left
u1 = g_ucLED[7] & 128;
for(i=0; i<8; i++)
{
u2 = g_ucLED[i];
g_ucLED[i] <<= 1;
if(u1) g_ucLED[i] |= 1;
u1 = u2 & 128;
}
}
}
//----------------------------------------------------------------------------
// MovingLightConstant
//
// moving light forward, constant speed, two groups eight leds each
// (red/blue mixed or separated)
//
// -> uTime = duration in ms of the pattern
// cMode = 0: mixed colors
// 1: red and blue separated
// 2: red only
// 3: blue only
// 4: blue only, gap of 15 LEDs of between each 4 LEDs on
// 5: red only, gap of 15 LEDs of between each 4 LEDs on
// 6: red/blue all on, gap of 8 LEDs moving
// 7: red/blue all on, 8 gaps of one LED moving
// 8: red/blue mixed all on, 8 gaps moving
// uDelay = time in ms between steps
// <- --
//----------------------------------------------------------------------------
void MovingLightConstant(unsigned int uTime, char cMode,
unsigned int uDelay)
{
int i;
// init LED buffer
for(i=0; i<8; i++) g_ucLED[i] = 0x00;
switch(cMode)
{
case 0:
g_ucLED[0] = 0xFF; g_ucLED[3] = 0xFF;
break;
case 1:
g_ucLED[0] = 0x55; g_ucLED[3] = 0xAA;
break;
case 2:
g_ucLED[0] = 0xAA; g_ucLED[3] = 0xAA;
break;
case 3:
g_ucLED[0] = 0x55; g_ucLED[3] = 0x55;
break;
case 4:
g_ucLED[0] = 0x01;
g_ucLED[2] = 0x01;
g_ucLED[4] = 0x01;
g_ucLED[6] = 0x01;
break;
case 5:
g_ucLED[0] = 0x02;
g_ucLED[2] = 0x02;
g_ucLED[4] = 0x02;
g_ucLED[6] = 0x02;
break;
case 6:
for(i=0; i<8; i++) g_ucLED[i] = 0xFF;
g_ucLED[0] = 0x00;
break;
case 7:
for(i=0; i<8; i++) g_ucLED[i] = 0xFE;
break;
case 8:
default:
for(i=0; i<8; i++) g_ucLED[i] = 0x50;
break;
}
g_uTimerRest = uTime;
while(g_uTimerRest)
{
switch(cMode)
{
case 0:
case 6:
case 7:
case 8:
BufRotateLeft(1);
break;
case 1:
case 2:
case 3:
case 4:
case 5:
default:
BufRotateLeft(2);
break;
}
SetLED();
// wait until next step
g_uTimer = 0; while(g_uTimer<uDelay);
}
}
//----------------------------------------------------------------------------
// SetBit
//
// set one bit in global LED buffer (numbered 0...63)
//
// -> iBit = number of bit to set
// <- --
//----------------------------------------------------------------------------
void SetBit(int iBit)
{
g_ucLED[iBit>>3] |= (1<<(iBit&0x07));
}
//----------------------------------------------------------------------------
// EyeBlink
//
// blinks with the 'eye'
//
// -> iNum = number of blinks
// iLength = duration in ms of one blink
// iPauseBetween = pause in ms between blinks
// iPauseAfter = pause in ms after the blinks
// iPauseBefore = pause in ms before the blinks
// <- --
//----------------------------------------------------------------------------
void EyeBlink(int iNum, int iLength, int iPauseBetween, int iPauseAfter,
int iPauseBefore)
{
int i;
// init LED buffer
for(i=0; i<8; i++) g_ucLED[i] = 0x00;
SetLED();
g_uTimer = 0; while(g_uTimer<iPauseBefore);
for(i=0; i<iNum; i++)
{
SetBit(62); SetLED();
g_uTimer = 0; while(g_uTimer<iLength);
g_ucLED[7] = 0; SetLED();
g_uTimer = 0; while(g_uTimer<iPauseBetween);
}
g_uTimer = 0; while(g_uTimer<iPauseAfter);
}
//----------------------------------------------------------------------------
// MovingLightsAntiDirection
//
// moving lights forward and backwards, separated by color
//
// -> uTime = duration in ms of the pattern
// uDelay = time in ms between the steps
// iNumRed = number of red LEDs to be on
// iNumBlue = number of blue LEDs to be on
// iDistance = distance of both groups (e. g. 31)
// <- --
//----------------------------------------------------------------------------
void MovingLightsAntiDirection(unsigned int uTime, unsigned int uDelay,
int iNumRed, int iNumBlue, int iDistance)
{
int i, iRed = 0, iBlue = iDistance, iRedPos, iBluePos;
g_uTimerRest = uTime;
while(g_uTimerRest)
{
// init LED buffer
for(i=0; i<8; i++) g_ucLED[i] = 0x00;
iRedPos = iRed;
iRed += 2; if(iRed>63) iRed -= 64;
for(i=0; i<iNumRed; i++)
{
SetBit(iRedPos);
iRedPos += 2; if(iRedPos>63) iRedPos -= 64;
}
iBluePos = iBlue;
iBlue -= 2; if(iBlue<0) iBlue += 64;
for(i=0; i<iNumBlue; i++)
{
SetBit(iBluePos);
iBluePos += 2; if(iBluePos>63) iBluePos -= 64;
}
SetLED();
// wait until next step
g_uTimer = 0; while(g_uTimer<uDelay);
}
}
//----------------------------------------------------------------------------
// Fading
//
// soft fading in and out the colors using PWM
//
// -> uTime = duration in ms of that pattern
// cMode = 0: alternating red and blue
// 1: red only
// 2: blue only
// 3: red and blue at the same time
// <- --
//----------------------------------------------------------------------------
void Fading(unsigned int uTime, char cMode)
{
int i;
unsigned char uc, ucPWMCounter = 0, ucPWMValue = 50, ucPWMDir = 0;
g_uTimerRest = uTime; g_uTimer = 0;
while(g_uTimerRest)
{
ucPWMCounter++; if(ucPWMCounter>=100) ucPWMCounter = 0;
// use global timer for brightness depending on current fading
// direction ucPWMDir
if(ucPWMDir==0)
{
ucPWMValue = g_uTimer/20;
}
else
{
ucPWMValue = 100 - g_uTimer/20;
}
if(g_uTimer>2000)
{
g_uTimer = 0;
// invert direction
ucPWMDir = (ucPWMDir) ? 0 : 1;
}
switch(cMode)
{
case 0:
uc = (ucPWMCounter<ucPWMValue) ? 0xAA : 0x55;
break;
case 1:
uc = (ucPWMCounter<ucPWMValue) ? 0xAA : 0x00;
break;
case 2:
uc = (ucPWMCounter<ucPWMValue) ? 0x55 : 0x00;
break;
case 3:
default:
uc = (ucPWMCounter<ucPWMValue) ? 0xFF : 0x00;
break;
}
// fill shift registers
for(i=0; i<8; i++)
{
SPDR = uc;
while(!(SPSR & (1<<SPIF)));
}
// clock the shift registers contents to their outputs
sbi(PORTB, 2); cbi(PORTB, 2);
}
}
//----------------------------------------------------------------------------
// main function
//----------------------------------------------------------------------------
int main(void)
{
// do all initializations
Init_IO();
// main loop
while(1)
{
EyeBlink(2, 100, 100, 1500, 500);
EyeBlink(2, 100, 100, 1500, 500);
MovingLightConstant(5000, 8, 66);
MovingLightsAntiDirection(8000, 25, 4, 4, 31);
MovingLightConstant(5000, 7, 100);
MovingLightConstant(5000, 6, 20);
MovingLightConstant(500, 3, 15);
MovingLightConstant(500, 2, 15);
MovingLightConstant(500, 3, 15);
MovingLightConstant(500, 2, 15);
MovingLightConstant(500, 3, 15);
MovingLightConstant(500, 2, 15);
EyeBlink(2, 100, 100, 1500, 500);
EyeBlink(2, 100, 100, 1500, 500);
MovingLightConstant(2500, 4, 250);
MovingLightConstant(500, 3, 15);
MovingLightConstant(500, 2, 15);
MovingLightConstant(500, 3, 15);
MovingLightConstant(500, 2, 15);
MovingLightConstant(500, 3, 15);
MovingLightConstant(500, 2, 15);
MovingLightConstant(2500, 5, 250);
Fading(4000, 1);
Fading(4000, 2);
Fading(4000, 1);
Fading(4000, 2);
Fading(8000, 0);
MovingLightConstant(4000, 2, 50);
Fading(8000, 1);
EyeBlink(2, 100, 100, 1500, 500);
EyeBlink(2, 100, 100, 1500, 500);
MovingLightConstant(6000, 3, 50);
MovingLightConstant(500, 3, 15);
MovingLightConstant(500, 2, 15);
MovingLightConstant(500, 3, 15);
MovingLightConstant(500, 2, 15);
MovingLightConstant(500, 3, 15);
MovingLightConstant(500, 2, 15);
Fading(8000, 2);
MovingLightConstant(4000, 0, 15);
Fading(8000, 3);
MovingLightConstant(6000, 1, 50);
}
}
|