
| Revised IgORElib | Main Sumo Program | Guardian Program |
You can download the files from here
#ifndef __SS_HARDWARE_H__
#define __SS_HARDWARE_H__
#include "igorelib.h"
#define BATTERY_VOLTAGE LIGHT_RIGHT
// I have connected a zener/resistor to the right photo diodes AD line to get the battery level
// *************************** Globals **************************
extern uint8 Meter_Mode;
extern uint8 Meter_Scan;
// *************************** Prototypes ***********************
void Reset_Hardware( void );
void Check_Sharp( void );
void Check_Battery( void );
void Sound(uint16 freq);
void Sound_Ramp( uint16 freq_start, uint16 freq_end, uint8 steps);
void Light_Display( uint8 pattern );
void Meter_Display( uint16 pattern );
void Meter_Set( uint16 pattern, uint8 meter);
void Meter_Update( void );
uint16 sample_AD( uint8 );
#endif
#include "SS_Hardware.h"
// *************************** Globals **************************
uint16 Meter_Bitmap = 0; // bit map to be sent to the level meter LEDS
uint8 Meter_Mode = AUTO_UPDATE; // Flag to control the mode of the level meters
uint8 Meter_Scan = ON; // Flag to control the cosmetic scanning of the top level meter
uint8 display_index = 0; // Used mainly for wakeup routine
uint8 Display_Bitmap = 0; // Used mainly for wakeup routine
//---------------------------------------------------------------
// Reset_Hardware
//
// Any additional hardware setup routines should be placed into this
// routine.
//
//---------------------------------------------------------------
void Reset_Hardware( void )
{
uint8 index;
if ( check_bumper(LEFT) )
// This is used to re-calibrate
{
// the ground IR sensors.
Sound_Ramp(100, 1000, 50);
set_line_threshold();
Sound_Ramp(1000, 100, 50);
}
for(index = 0; index < 4; index++) // General pause to let subsystems start
{
// and to make sure that shift registers for
delay_ms(250); // LEDs are blank
Light_Display(0x00);
Meter_Display(0x0000);
}
}
//---------------------------------------------------------------
// Check_Battery
//
// This will give a meter-like reading on the left line of the front
// meter display based on a reading from the battery level. The
// battery level was taken from the right photo ADC line because
// I never did install the photo diode into that side, so it was
// the easiest to steal. =)
//
// This is to give some kind of social interaction to any
// viewers, other than just blinky lights.
//---------------------------------------------------------------
void Check_Battery( void )
{
uint16 battery_level = 0;
battery_level = sample_AD(BATTERY_VOLTAGE); // Get current battery level
if ( battery_level > 0x03B0 )
Meter_Set(0x1F, 3);
else if ( battery_level > 0x0300 )
Meter_Set(0x0F, 3);
else if ( battery_level > 0x02A0 )
Meter_Set(0x07, 3);
else if ( battery_level > 0x0250 )
Meter_Set(0x03, 3);
else if ( battery_level > 0x0200 )
Meter_Set(0x01, 3);
else
Meter_Set(0x00, 3);
}
//---------------------------------------------------------------
// Check_Sharp
//
// This will give a meter-like reading on two of the front meter
// displays.
//
// This is to give some kind of social interaction to any
// viewers, other than just blinky lights.
//---------------------------------------------------------------
void Check_Sharp( void )
{
uint8 ir_reading;
ir_reading = read_sharp_cm(LEFT); // Get current Sharp Reading
if ( ir_reading < 10 ) // Display it to one of the level meters
Meter_Set(0x1F, 2);
else if ( ir_reading < 15 )
Meter_Set(0x0F, 2);
else if ( ir_reading < 20 )
Meter_Set(0x07, 2);
else if ( ir_reading < 25 )
Meter_Set(0x03, 2);
else if ( ir_reading < 40 )
Meter_Set(0x01, 2);
else
Meter_Set(0x00, 2);
}
//---------------------------------------------------------------
// Sound
//
// This function is connected to a piezo electric speaker/buzzer
// on port B, pin 5. The other side is connected to +5V.
//
// This is to give some kind of social interaction to any
// viewers, other than just blinky lights.
//---------------------------------------------------------------
void Sound(uint16 freq)
{
uint16 inv_freq;
uint16 duration = freq/100;
// This seemed to be a nice length
if ( read_switch(2) )
// Check for mute switch
{
if (freq > 1000)
// If freq asked for is too high, another time delay function
{
// needs to be used (delay_us vs. delay_ms)
inv_freq = 1000000/freq;
while (duration > 0)
{
PORTBbits.RB5 = 0;
delay_us(inv_freq);
PORTBbits.RB5 = 1;
delay_us(inv_freq);
duration--;
}
}
else
{
inv_freq = 1000/freq;
// (1/freq) * 20000/2 ---> the 2 is from the fact that half the wave is on, and half is off
while (duration > 0)
{
PORTBbits.RB5 = 0;
delay_ms(inv_freq);
PORTBbits.RB5 = 1;
delay_ms(inv_freq);
duration--;
}
}
}
}
//---------------------------------------------------------------
// Sound_Ramp
//
// Just a little something to augment the Sound() function.
//
// This is to give some kind of social interaction to any
// viewers, other than just blinky lights.
//---------------------------------------------------------------
void Sound_Ramp( uint16 freq_start, uint16 freq_end, uint8 steps)
{
uint16 step_size;
if ( read_switch(2) )
// Check for mute switch (This is checked here as well as the other
{
// sound function, so time isn't wasted on a routine that doesn't need
// to be run when the switch is off)
if (freq_start < freq_end)
// Sound ramping up
{
step_size = (freq_start - freq_end)/ steps;
while(freq_start < freq_end)
{
Sound(freq_start);
freq_start += step_size;
}
Sound(freq_end);
}
else
// Sound ramping down
{
step_size = (freq_end - freq_start)/ steps;
while(freq_start >
freq_end)
{
Sound(freq_start);
freq_start -= step_size;
}
Sound(freq_end);
}
}
}
//****************************************************************************
// Light_Display
//
// Additional hardware to the igore produced by Nicholas Cogghe has required
// certain additional calls to access this hardware. Display lights for the
// top of Igore have been added for debugging and/or entertainment purposes.
//
// This hardware is a simple shift register attached to 8 LEDs.
//
//TODO: no control over the Master Reset from the shift register is
//available, this would be handy in the future.
//
//****************************************************************************
void Light_Display( uint8 pattern )
{
int index;
for(index = 0; index < 8; index++)
{
PORTDbits.RD3 = !(0x01 & pattern);
// Put Data to Pin D3
// Pause for Effect/Applause
PORTDbits.RD2 = 1;
PORTDbits.RD2 = 0;
pattern = pattern >> 1;
// Lather, Rinse, Repeat.
}
}
//****************************************************************************
// Meter_Display
//
// Additional hardware to the igore produced by Nicholas Cogghe has required
// certain additional calls to access this hardware. Display lights for the
// top of Igore have been added for debugging and/or entertainment purposes.
//
// This hardware is a simple shift register attached to 8 LEDs. (NOTE: Last
// bit is not connected to any LED in hardware)
//
//TODO: no control over the Master Reset from the shift register is
//available, this would be handy in the future.
//
//****************************************************************************
void Meter_Display( uint16 pattern )
{
int index;
for(index = 0; index < 16; index++)
{
PORTDbits.RD4 = !(0x01 & pattern);
// Put Data to Pin D3
// Pause for Effect/Applause
PORTAbits.RA4 = 1;
// Clock goes up,
PORTAbits.RA4 = 0;
// Clock goes down
pattern = pattern >> 1;
// Lather, Rinse, Repeat.
}
}
//****************************************************************************
// Meter_Set
//
// Additional hardware to the igore produced by Nicholas Cogghe has required
// certain additional calls to access this hardware. Display lights for the
// top of Igore have been added for debugging and/or entertainment purposes.
//
// This routine is used to turn on or off the front meter lights,
// yet changes to the lights will not be noticeable until the 10Hz
// update clock calls the Meter_Update routine.
//
// NOTE: This routine is only useful if the flag Meter_Mode is in
// AUTO_UPDATE mode. Otherwise, no updates will occur.
//****************************************************************************
void Meter_Set(uint16 pattern, uint8 meter)
{
uint16 new_pattern = 0x001F & pattern;
// Each meter only contains 5 LEDs
new_pattern = new_pattern << 1;
switch(meter)
{
case 0:
// Set all meters to same value
Meter_Bitmap = (Meter_Bitmap & 0xFFC1) | new_pattern;
new_pattern = new_pattern << 5;
Meter_Bitmap = (Meter_Bitmap & 0xF83F) | new_pattern;
new_pattern = new_pattern << 5;
Meter_Bitmap = (Meter_Bitmap & 0x07FF) | new_pattern;
break;
case 1:
// Meter 1, top row, LED 1 (far left/outside)
Meter_Bitmap = (Meter_Bitmap & 0xFFC1) | new_pattern;
break;
case 2:
// Meter 2, Left Vertical Row (Outside), LED 1 bottom
new_pattern = new_pattern << 5;
Meter_Bitmap = (Meter_Bitmap & 0xF83F) | new_pattern;
break;
case 3:
// Meter 3, Right Vertical Row (Inside), LED 1 bottom
new_pattern = new_pattern << 10;
Meter_Bitmap = (Meter_Bitmap & 0x07FF) | new_pattern;
break;
}
}
// --------------------------------------------------------------
// Meter_Update
//
// This function was created to operate as an update routine
// to be triggered by an interrupt. This will be updated by the
// 10Hz clock, when it is in auto_update move.
//
// This routine is specifically ornamental, to give the robot a
// bit of class.
// --------------------------------------------------------------
void Meter_Update( void )
{
static uint8 Scan_Position = 0, Scan_Dir = RIGHT;
int index;
uint16 pattern = Meter_Bitmap;
if (Meter_Scan == ON)
// The Meter_Scan routines only serves
{
// cosmetic and haptic purposes
if (Scan_Dir == RIGHT)
{
Scan_Position++;
if (Scan_Position == 4)
Scan_Dir = LEFT;
}
else
{
Scan_Position--;
if (Scan_Position == 0)
Scan_Dir = RIGHT;
}
switch(Scan_Position)
{
case 0:
Meter_Set(0x01, 1); break;
case 1:
Meter_Set(0x02, 1); break;
case 2:
Meter_Set(0x04, 1); break;
case 3:
Meter_Set(0x08, 1); break;
case 4:
Meter_Set(0x10, 1); break;
}
}
// End of Meter_Scan cosmetic routines
for(index = 0; index < 16; index++)
// This is to actually shove the data to the shift register
{
PORTDbits.RD4 = !(0x01 & pattern);
// Put Data to Pin D3
// Pause for Effect/Applause =)
PORTAbits.RA4 = 1;
// Clock goes up,
PORTAbits.RA4 = 0;
// Clock goes down
pattern = pattern >> 1;
// Lather, Rinse, Repeat.
}
}