Code
/*
* File: Fount_test.c
* Author: Nolander
*
* Created on October 4, 2013, 3:44 PM
*/
/*
*
*/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* I N C L U D E S
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#if defined(__XC)
#include <xc.h> /* XC8 General Include File */
#elif defined(HI_TECH_C)
#include <htc.h> /* HiTech General Include File */
#elif defined(__18CXX)
#include <p18cxxx.h> /* C18 General Include File */
#endif
#if defined(__XC) || defined(HI_TECH_C)
#include <stdint.h> /* For uint8_t definition */
#include <stdbool.h> /* For true/false definition */
#endif
#include <usart.h>
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* C O N F I G S
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#define FOUNT_ID 1
#pragma config XINST = ON
#pragma config SOSCSEL = HIGH
#define DEBUG 0
#define DEBUG2 1
#pragma config WDTEN = OFF //WDT disabled (enabled by SWDTEN bit)
// ...
//set internal clock to 8 MHz (default)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* D E F I N E S
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//MAIN
#define DEBOUNCE_TIME 10
#define TIMER_1_INTERRUPT_FLAG PIR1bits.TMR1IF
#define TIMER_3_INTERRUPT_FLAG PIR2bits.TMR3IF
#define TIMER_1_INTERRUPT_ENABLED PIE1bits.TMR1IE
#define TIMER_3_INTERRUPT_ENABLED PIE2bits.TMR3IE
#define RISING_EDGE_INTERRUPT_FLAG PIR4bits.CCP4IF
#define RISING_EDGE_INTERRUPT_ENABLED PIE4bits.CCP4IE
#define FALLING_EDGE_INTERRUPT_FLAG PIR4bits.CCP5IF
#define FALLING_EDGE_INTERRUPT_ENABLED PIE4bits.CCP5IE
#define AT_HOME INTCON2bits.INTEDG0
#define FALSE 0
#define TRUE 1
#define PULSES_REQUIRED 10
#define POUR_ACTION_COMPLETION_COUNT 69
#define POUR_ACTION_BROKEN_COUNT 5
#define WRAPUP_COMPLETION_COUNT 140
#if FOUNT_ID == 1
#define MAX_PULSE_WIDTH 8//300Hz //lower value filters out lower frequency range
#define MIN_PULSE_WIDTH 5/////// //higher value filters out higher frequency range
#elif FOUNT_ID == 2
#define MAX_PULSE_WIDTH 4//600Hz //lower value filters out lower frequency range
#define MIN_PULSE_WIDTH 2////////higher value filters out higher frequency range
#endif
#if DEBUG2
#define FALL CCPR5H
#define RISE CCPR4H
#define TFALL TMR3H
#define TRISE TMR5H
#else
#define FALL CCPR5L
#define RISE CCPR4L
#define TFALL TMR3L
#define TRISE TMR5L
#define MAX_PULSE_WIDTH 250
#define MIN_PULSE_WIDTH 200
#endif
//VISUAL
#if FOUNT_ID == 1
#define MY_COLOR 'g'
#elif FOUNT_ID == 2
#define MY_COLOR 'b'
#else
#define MY_COLOR 'w'
#endif
#define SCLK PORTCbits.RC2
#define SOUT PORTCbits.RC3
#define BLANK PORTCbits.RC4
#define XLAT PORTCbits.RC5
#define MAX_STEP 255
#define HALF_STEP 50
#define POUR_TIME 5
//AUDIO
#define TRACK1 LATAbits.LATA1
#define TRACK2 LATAbits.LATA2
#define TRACK3 LATAbits.LATA3
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* V A R I A B L E S
*
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//visual
unsigned int pwmbuffer[24]; // Brightness buffer
int b, c, i, j, k; // Loop variables
unsigned int d; // for delay function only
int fillLevel;
//Main
int pulse_counter = 0;
int pour_action_counter = 0;
int pour_action_broken_counter = 0;
int shutdown = 0;
int gameover = 0;
int pouring = 0;
//xbee
const unsigned char delimiter = 0x7E;
unsigned char length;
unsigned char frameType = 0x10;
unsigned char frameID = 0x01;
unsigned char radius = 0x00;
unsigned char options = 0x00;
char checkSum = 0x00;
#define LED1 LATAbits.LATA1
#define LED2 LATAbits.LATA2
#define LED3 LATAbits.LATA3
#define ON 1
#define OFF 0
#define TMR3 (TMR3H << 8) + TMR3L
#define TMR5 (TMR5H << 8) + TMR5L
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* F U N C T I O N S
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//Timer 0 8 or 16 bit interrupt on overflow
//Timer 1 16 bit interrupt on overflow
//Timer 2 8 bit interrupt on PR2 match
//Timer 3 / 5 16 bit interrupt on overflow
//Timer 4 / 6 / 8 8 bit interrupt on PRx match
//audio
void playAudio( unsigned int track );
//xbee
void notifyEndGame(void);
void notifyCupLeft(void);
//signed char strcmppgm2ram(const char * str1, const rom char * str2 );
//visual functions
void pourLEDs( char color,int step );
void followLEDs( char color, int step,int loop);
void fadeLEDs(char color, int step);
void flashLEDs(char color, int time,int brightness);
void fillLEDs( char color, int step );
void randomLED( int step );
void delay( int cycles );
void setLED( int lednum, int r, int g, int b);
void setPWM( int chan, int pwm);
void writeLED( void );
void clearAll( void );
void main( void )
{
//RCONbits.IPEN = 1;
INTCONbits.GIEL = 1;
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
//INIT TIMER1
//T1CON = 0b10001101;
PIR1bits.TMR1IF = 0; //Timer 1 Interrupt Flag
TIMER_1_INTERRUPT_ENABLED = TRUE; //Timer 1 Interrupt Enable
// T1CONbits.T1OSCEN = 1; // bit 3 Timer1 Oscillator Enable Control bit 1 = on
// T1CONbits.NOT_T1SYNC = 1; // bit 2 Timer1 External Clock Input Synchronization Control bit...1 = Do not synchronize external clock input
//T1CONbits.TMR1CS = 2; // bit 1 Timer1 Clock Source Select bit...0 = Internal clock (FOSC/4)
T1CONbits.TMR1ON = 1;//1;
//INIT LEDS
TRISAbits.TRISA1 = 0;//output
TRISAbits.TRISA2 = 0;
TRISAbits.TRISA3 = 0;
LED1 = LED2 = OFF;
LED3 = OFF;
//INIT CAPTURE RISING CCP4
CCPTMRS1bits.C4TSEL = 1;//CCP4 is based off of timer 3
CCP4CONbits.CCP4M = 0x05; //sets CCP2 to capture rising edge
TRISBbits.TRISB4 = 1;//enables input on pin CCP4
T3CONbits.TMR3ON = 1;
//T3CONbits.T3OSCEN = 1; // bit 3 Timer1 Oscillator Enable Control bit 1 = on
RISING_EDGE_INTERRUPT_ENABLED = FALSE;
//INIT CAPTURE FALLING CCP5
CCPTMRS1bits.C5TSEL0 = 1;//CCP5 is based off of timer 5
CCP5CONbits.CCP5M = 0x04; //sets CCP2 to capture falling edge
TRISBbits.TRISB5 = 1;//enables input on pin CCP5
T5CONbits.TMR5ON = 1;
// T5CONbits.T5OSCEN = 1; // bit 3 Timer1 Oscillator Enable Control bit 1 = on
FALLING_EDGE_INTERRUPT_ENABLED = TRUE;
//INIT BUTTON PRESS
INTCON2bits.INTEDG0 = 1;
INTCONbits.INT0E = 1;//from low to high(i.e. cup pulls the fount low; waiting for removal of cup)
INTCONbits.INT0F = 0;
TRISBbits.TRISB0 = 1;//input
ANCON1bits.PCFG12 = 1; //digital port
//INIT AUDIO
TRACK1 = TRACK2 = TRACK3 = 1;
//INIT VISUAL
TRISCbits.TRISC2 = TRISCbits.TRISC3 = TRISCbits.TRISC4 = TRISCbits.TRISC5 = 0;//output
SCLK = 0;
SOUT = 0;
BLANK = 0;
XLAT = 0;
//INIT XBEE
TRISBbits.TRISB1 = 0; //TX
TRISBbits.TRISB4 = 1; //RX
Open1USART(USART_TX_INT_OFF & USART_RX_INT_OFF
& USART_ASYNCH_MODE & USART_EIGHT_BIT
& USART_SINGLE_RX & USART_BRGH_LOW, 6); // try 12, 51, 207
Delay1KTCYx(4);
// process loop
//Write1USART('c');
while(!shutdown){
if(AT_HOME){
fadeLEDs(MY_COLOR, 10);
}
else {
fadeLEDs('r', 10);
}
if(gameover){
TIMER_1_INTERRUPT_ENABLED = FALSE;
FALLING_EDGE_INTERRUPT_ENABLED = FALSE;
RISING_EDGE_INTERRUPT_ENABLED = FALSE;
followLEDs(MY_COLOR,200,5);
notifyEndGame();
}
else if(pouring){
fillLEDs('b', 10);
}
}
}
void notifyEndGame(void){
// Start Delimiter
int i = 0;
while(Busy1USART());
Write1USART(delimiter);
// Length
// 14 + 9 = 23 in hex
while(Busy1USART());
Write1USART(0x00);
while(Busy1USART());
// Payload length + FrameTypeLen + FrameIDLen + 64DestAddressLen + 16DestLen + RadiusLen + optionsLen
Write1USART(9 + 14);
// Frame Type
while(Busy1USART());
Write1USART(frameType);
// Frame ID - API Mode 1
while(Busy1USART());
Write1USART(frameID);
checkSum += frameID;
// 64-bit Destination Address
// All Zeros
for (i = 0; i < 8; i++)
{
while(Busy1USART());
Write1USART(0x00);
checkSum += frameID;
}
// 16-bit Address
// 0xFFFE
while(Busy1USART());
Write1USART(0xFF);
checkSum += 0xFF;
while(Busy1USART());
Write1USART(0xFE);
checkSum += 0xFE;
// Broadcast Radius
while(Busy1USART());
Write1USART(radius);
checkSum += radius;
// Options
// Checksum = 17 here
while(Busy1USART());
Write1USART(options);
checkSum += options;
// Payload
// Fount1Win = 9 Bytes
while(Busy1USART());
Write1USART('F');
while(Busy1USART());
Write1USART('1');
while(Busy1USART());
Write1USART('W');
while(Busy1USART());
Write1USART('I');
while(Busy1USART());
Write1USART('N');
checkSum += 5;
// Checksum: total bytes = 26
// in Hex
checkSum = (char)(0xFF - (char)checkSum);
while(Busy1USART());
Write1USART((char)checkSum);
shutdown = TRUE;
}
void notifyCupLeft(void){
// Start Delimiter
int i = 0;
while(Busy1USART());
Write1USART(delimiter);
// Length
// 14 + 9 = 23 in hex
while(Busy1USART());
Write1USART(0x00);
while(Busy1USART());
// Payload length + FrameTypeLen + FrameIDLen + 64DestAddressLen + 16DestLen + RadiusLen + optionsLen
Write1USART(9 + 14);
// Frame Type
while(Busy1USART());
Write1USART(frameType);
// Frame ID - API Mode 1
while(Busy1USART());
Write1USART(frameID);
checkSum += frameID;
// 64-bit Destination Address
// All Zeros
for (i = 0; i < 8; i++)
{
while(Busy1USART());
Write1USART(0x00);
checkSum += frameID;
}
// 16-bit Address
// 0xFFFE
while(Busy1USART());
Write1USART(0xFF);
checkSum += 0xFF;
while(Busy1USART());
Write1USART(0xFE);
checkSum += 0xFE;
// Broadcast Radius
while(Busy1USART());
Write1USART(radius);
checkSum += radius;
// Options
// Checksum = 17 here
while(Busy1USART());
Write1USART(options);
checkSum += options;
// Payload
// Fount1Win = 9 Bytes
while(Busy1USART());
Write1USART('F');
while(Busy1USART());
Write1USART('1');
while(Busy1USART());
Write1USART('O');
while(Busy1USART());
Write1USART('F');
while(Busy1USART());
Write1USART('F');
checkSum += 5;
// Checksum: total bytes = 26
// in Hex
checkSum = (char)(0xFF - (char)checkSum);
while(Busy1USART());
Write1USART((char)checkSum);
}
#pragma code highPriorityInterrupts = 0x08
#pragma interrupt highPriorityInterrupts
void highPriorityInterrupts( void ){
if(FALLING_EDGE_INTERRUPT_FLAG){
FALLING_EDGE_INTERRUPT_ENABLED = FALSE;
if(((FALL - RISE) > MIN_PULSE_WIDTH) & ((FALL - RISE) < MAX_PULSE_WIDTH)){
pour_action_broken_counter = 0;
pulse_counter ++;
if(~pouring & (pulse_counter > PULSES_REQUIRED)){
pouring = TRUE;
playAudio(2);
}
}
else{
pulse_counter = 0;
}
//reset capture timer values
TFALL = 0;
TRISE = 0;
FALLING_EDGE_INTERRUPT_FLAG = FALSE;
FALLING_EDGE_INTERRUPT_ENABLED = TRUE;
}
if(RISING_EDGE_INTERRUPT_FLAG){//need this in order to clear the FLAG
RISING_EDGE_INTERRUPT_FLAG = FALSE;
}
if(INTCONbits.INT0F){//BUTTON PRESS
Delay1KTCYx(DEBOUNCE_TIME);
INTCONbits.INT0E = 0;
playAudio(1);
if(INTCON2bits.INTEDG0){
notifyCupLeft();
}
INTCON2bits.INTEDG0 ^= 1; //ATHOME = !ATHOME
INTCONbits.INT0F = 0;
INTCONbits.INT0E = 1;
}
if(TIMER_1_INTERRUPT_FLAG){//pour completion, pour broken, or wrap up completion
TIMER_1_INTERRUPT_ENABLED = FALSE;
if(pouring){
pour_action_broken_counter++;
}
if(pour_action_broken_counter > POUR_ACTION_BROKEN_COUNT){
pouring = FALSE;
pulse_counter = 0;
}
TIMER_1_INTERRUPT_FLAG = FALSE;
TIMER_1_INTERRUPT_ENABLED = TRUE;
}
}
void playAudio( unsigned int track )
{
switch(track)
{
case 1:
//Set pin to Low to play the track
TRACK1 = 0;
//Delay to make sure the pin is grounded
Delay1KTCYx(100);
//Set pin back to high so it can be played again later
TRACK1 = 1;
break;
case 2:
//Set pin to low to play the track
TRACK2 = 0;
//Delay to make sure the pin is grounded
Delay1KTCYx(100);
//Set pin back to high so it can be played again later
TRACK2 = 1;
break;
case 3:
//Set pin to low to play the track
TRACK3 = 0;
//Delay to make sure the pin is grounded
Delay1KTCYx(100);
//Set pin back to high so it can be played again later
TRACK3 = 1;
break;
}
}
void pourLEDs( char color, int timer )
{
int scaledTime;
scaledTime = (MAX_STEP / POUR_TIME) * timer;
for (i = 0; i < 8; i++)
{
if (color == 'r')
setLED(i, scaledTime, 0, 0);
if (color == 'g')
setLED(i, 0, scaledTime, 0);
if (color == 'b')
setLED(i, 0, 0, scaledTime);
}
writeLED();
}
void followLEDs( char color, int step, int loop)
{
int firstLoop = 1;
while (loop >= 0 )
{
for (i = 0; i < 8; i++)
{
if (i == 0 && firstLoop)
for (j = 0; j < MAX_STEP; j++)
{
if (color == 'r')
setLED(i, j, 0, 0);
if (color == 'g')
setLED(i, 0, j, 0);
if (color == 'b')
setLED(i, 0, 0, j);
if (color == 'y')
setLED(i, j, j, 0);
if (color == 'c')
setLED(i, 0, j, j);
if (color == 'm')
setLED(i, j, 0, j);
if (color == 'w')
setLED(i, j, j, j);
writeLED();
j = j + step;
firstLoop = 0;
}
if (i > 0)
{
for (j = 0, k = MAX_STEP; j < MAX_STEP || k > 0; j++, k--)
{
if (color == 'r')
{
setLED(i, j, 0, 0);
setLED(i-1, k, 0, 0);
}
if (color == 'g')
{
setLED(i, 0, j, 0);
setLED(i-1, 0, k, 0);
}
if (color == 'b')
{
setLED(i, 0, 0, j);
setLED(i-1, 0, 0, k);
}
if (color == 'y')
{
setLED(i, j, j, 0);
setLED(i-1, k, k, 0);
}
if (color == 'c')
{
setLED(i, 0, j, j);
setLED(i-1, 0, k, k);
}
if (color == 'm')
{
setLED(i, j, 0, j);
setLED(i-1, k, 0, k);
}
if (color == 'w')
{
setLED(i, j, j, j);
setLED(i-1, k, k, k);
}
writeLED();
j = j + step;
k = k - step;
}
setLED(i-1, 0, 0, 0);
writeLED();
}
if (i == 7)
{
for (j = 0, k = MAX_STEP; j < MAX_STEP, k > 0; k++, j--)
{
if (color == 'r'){
if (loop > 0)
setLED(0, j, 0, 0);
setLED(i, k, 0, 0);
}
if (color == 'g'){
if (loop > 0)
setLED(0, 0, j, 0);
setLED(i, 0, k, 0);
}
if (color == 'b'){
if (loop > 0)
setLED(0, 0, 0, j);
setLED(i, 0, 0, k);
}
if (color == 'y'){
if (loop > 0)
setLED(0, j, j, 0);
setLED(i, k, k, 0);
}
if (color == 'c'){
if (loop > 0)
setLED(0, 0, j, j);
setLED(i, 0, k, k);
}
if (color == 'm'){
if (loop > 0)
setLED(0, j, 0, j);
setLED(i, k, 0, k);
}
if (color == 'w'){
if (loop > 0)
setLED(0, j, j, j);
setLED(i, k, k, k);
}
writeLED();
k = k - step;
}
setLED(i, 0, 0, 0);
writeLED();
}
}
loop--;
}
}
void fillLEDs( char color, int step )
{
for (i = 0; i < 8; i++){
if(pouring == FALSE){
// clearAll();/*
playAudio(2);//stop splashing effect
for (i; i>=0; i--)
{
for (j = HALF_STEP; j > 0; j--)
{
if (color == 'r')
setLED(i, j, 0, 0);
if (color == 'g')
setLED(i, 0, j, 0);
if (color == 'b')
setLED(i, 0, 0, j);
if (color == 'y')
setLED(i, j, j, 0);
if (color == 'c')
setLED(i, 0, j, j);
if (color == 'm')
setLED(i, j, 0, j);
if (color == 'w')
setLED(i, j, j, j);
writeLED();
j = j - step;
}
setLED(i, 0, 0, 0);
writeLED();
}//*/
// FALLING_EDGE_INTERRUPT_ENABLED = TRUE;
return;
}
for (j = 0; j < MAX_STEP; j++)
{
if (color == 'r')
setLED(i, j, 0, 0);
if (color == 'g')
setLED(i, 0, j, 0);
if (color == 'b')
setLED(i, 0, 0, j);
if (color == 'y')
setLED(i, j, j, 0);
if (color == 'c')
setLED(i, 0, j, j);
if (color == 'm')
setLED(i, j, 0, j);
if (color == 'w')
setLED(i, j, j, j);
writeLED();
j = j + step;
}
}
pouring = FALSE;
gameover = TRUE;
playAudio(1);
/*
for (i = 0; i < 8; i++)
{
for (j = MAX_STEP; j > 0; j--)
{
if (color == 'r')
setLED(i, j, 0, 0);
if (color == 'g')
setLED(i, 0, j, 0);
if (color == 'b')
setLED(i, 0, 0, j);
if (color == 'y')
setLED(i, j, j, 0);
if (color == 'c')
setLED(i, 0, j, j);
if (color == 'm')
setLED(i, j, 0, j);
if (color == 'w')
setLED(i, j, j, j);
writeLED();
j = j - step;
}
setLED(i, 0, 0, 0);
writeLED();
}*/
}
void flashLEDs(char color, int time, int brt)
{
for (i = 0; i < 8; i++)
{
if (color == 'r')
setLED(i, brt, 0, 0);
if (color == 'g')
setLED(i, 0, brt, 0);
if (color == 'b')
setLED(i, 0, 0, brt);
if (color == 'c')
setLED(i, 0, brt, brt);
if (color == 'y')
setLED(i, brt, brt, 0);
if (color == 'm')
setLED(i, brt, 0, brt);
if (color == 'w')
setLED(i, brt, brt, brt);
}
writeLED();
// Delay function times 10
for(i = 0; i < 10; i++)
delay(time);
// Turn off all LEDs
clearAll();
for(i = 0; i < 10; i++)
delay(time);
}
void fadeLEDs(char color, int step)
{
for (i = 0; i < MAX_STEP; i++)
{
if(pouring){
clearAll();
return;
}
for (j = 0; j < 8; j++)
{
if (color == 'r')
setLED(j, i, 0, 0);
if (color == 'g')
setLED(j, 0, i, 0);
if (color == 'b')
setLED(j, 0, 0, i);
if (color == 'y')
setLED(j, i, i, 0);
if (color == 'c')
setLED(j, 0, i, i);
if (color == 'm')
setLED(j, i, 0, i);
if (color == 'w')
setLED(j, i, i, i);
}
writeLED();
i = i + step;
}
for (i = MAX_STEP; i > 0; i--)
{
if(pouring){
clearAll();
return;
}
for (j = 0; j < 8; j++)
{
if (color == 'r')
setLED(j, i, 0, 0);
if (color == 'g')
setLED(j, 0, i, 0);
if (color == 'b')
setLED(j, 0, 0, i);
if (color == 'y')
setLED(j, i, i, 0);
if (color == 'c')
setLED(j, 0, i, i);
if (color == 'm')
setLED(j, i, 0, i);
if (color == 'w')
setLED(j, i, i, i);
}
writeLED();
i = i - step;
}
}
void setLED(int lednum, int r, int g, int b)
{
setPWM(lednum*3, b);
setPWM(lednum*3+1, g);
setPWM(lednum*3+2, r);
}
void setPWM(int chan, int pwm)
{
if (pwm > MAX_STEP) pwm = 255;
if (chan > 24) return;
pwmbuffer[chan] = pwm;
}
void clearAll( void )
{
for (i = 0; i < 24; i++)
pwmbuffer[i] = 0;
writeLED();
}
void writeLED( void )
{
XLAT = 0;
for (c = 23; c >= 0; c--)
{
for (b = 11; b >= 0; b--)
{
SCLK = 0;
delay(2);
if ( pwmbuffer[c] & (1 << b) )
SOUT = 1;
else
SOUT = 0;
SCLK = 1;
}
}
SCLK = 0;
BLANK = 1;
XLAT = 1;
BLANK = 0;
XLAT = 0;
}
void delay(int cycles )
{
for (d = 0; d < cycles; d++);
}