Untitled diff

Created Diff never expires
17 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
287 lines
26 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
296 lines
*Settings to modify per driver
#define F_CPU 4800000UL
/*
* =========================================================================
* Settings to modify per driver
*/
*/
#define VOLTAGE_MON // Comment out to disable
#define VOLTAGE_MON // Comment out to disable
#define MODE_MOON 1 // Can comment out to remove mode, but should be set through soldering stars
#define MODE_MOON 8 // Can comment out to remove mode, but should be set through soldering stars
#define MODE_1 8 // Can comment out to remove mode
#define MODE_LOW 14 // Can comment out to remove mode
#define MODE_2 75 // Can comment out to remove mode
#define MODE_MED 39 // Can comment out to remove mode
#define MODE_HIGH_W_TURBO 110 // MODE_HIGH value when turbo is enabled
#define MODE_HIGH 120 // Can comment out to remove mode
#define MODE_TURBO 255 // Can comment out to remove mode
#define MODE_TURBO 255 // Can comment out to remove mode
#define TURBO_TIMEOUT 37 // How many WTD ticks before before dropping down (.5 sec each)
#define TURBO_TIMEOUT 240 // How many WTD ticks before before dropping down (.5 sec each)
#define WDT_TIMEOUT 2 // Number of WTD ticks before mode is saved (.5 sec each)
#define WDT_TIMEOUT 2 // Number of WTD ticks before mode is saved (.5 sec each)
#define ADC_LOW 130 // When do we start ramping
#define ADC_LOW 130 // When do we start ramping
#define ADC_CRIT 120 // When do we shut the light off
#define ADC_CRIT 120 // When do we shut the light off
/*
/*
* =========================================================================
* =========================================================================
*/
*/
#ifdef MODE_TURBO
#ifdef MODE_TURBO
#undef MODE_HIGH
#undef MODE_HIGH
#define MODE_HIGH MODE_HIGH_W_TURBO
#define MODE_HIGH MODE_HIGH_W_TURBO
#endif
#endif
//#include <avr/pgmspace.h>
//#include <avr/pgmspace.h>
#include <avr/io.h>
#include <avr/io.h>
#include <util/delay.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include <avr/eeprom.h>
#include <avr/sleep.h>
#include <avr/sleep.h>
//#include <avr/power.h>
//#include <avr/power.h>
#define STAR2_PIN PB0
#define STAR2_PIN PB0
#define STAR3_PIN PB4
#define STAR3_PIN PB4
#define STAR4_PIN PB3
#define STAR4_PIN PB3
#define PWM_PIN PB1
#define PWM_PIN PB1
#define VOLTAGE_PIN PB2
#define VOLTAGE_PIN PB2
#define ADC_CHANNEL 0x01 // MUX 01 corresponds with PB2
#define ADC_CHANNEL 0x01 // MUX 01 corresponds with PB2
#define ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2
#define ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2
#define ADC_PRSCL 0x06 // clk/64
#define ADC_PRSCL 0x06 // clk/64
#define PWM_LVL OCR0B // OCR0B is the output compare register for PB1
#define PWM_LVL OCR0B // OCR0B is the output compare register for PB1
/*
/*
* global variables
* global variables
*/
*/
// Mode storage
// Mode storage
uint8_t eepos = 0;
uint8_t eepos = 0;
uint8_t eep[32];
uint8_t eep[32];
uint8_t memory = 0;
uint8_t memory = 0;
// Modes (gets set when the light starts up based on stars)
// Modes (gets set when the light starts up based on stars)
static uint8_t modes[10]; // Don't need 10, but keeping it high enough to handle all
static uint8_t modes[10]; // Don't need 10, but keeping it high enough to handle all
volatile uint8_t mode_idx = 0;
volatile uint8_t mode_idx = 0;
int mode_dir = 0; // 1 or -1. Determined when checking stars. Do we increase or decrease the idx when moving up to a higher mode.
int mode_dir = 0; // 1 or -1. Determined when checking stars. Do we increase or decrease the idx when moving up to a higher mode.
uint8_t mode_cnt = 0;
uint8_t mode_cnt = 0;
uint8_t lowbatt_cnt = 0;
uint8_t lowbatt_cnt = 0;
void store_mode_idx(uint8_t lvl) { //central method for writing (with wear leveling)
void store_mode_idx(uint8_t lvl) { //central method for writing (with wear leveling)
uint8_t oldpos=eepos;
uint8_t oldpos=eepos;
eepos=(eepos+1)&31; //wear leveling, use next cell
eepos=(eepos+1)&31; //wear leveling, use next cell
// Write the current mode
// Write the current mode
EEARL=eepos; EEDR=lvl; EECR=32+4; EECR=32+4+2; //WRITE //32:write only (no erase) 4:enable 2:go
EEARL=eepos; EEDR=lvl; EECR=32+4; EECR=32+4+2; //WRITE //32:write only (no erase) 4:enable 2:go
while(EECR & 2); //wait for completion
while(EECR & 2); //wait for completion
// Erase the last mode
// Erase the last mode
EEARL=oldpos; EECR=16+4; EECR=16+4+2; //ERASE //16:erase only (no write) 4:enable 2:go
EEARL=oldpos; EECR=16+4; EECR=16+4+2; //ERASE //16:erase only (no write) 4:enable 2:go
}
}
inline void read_mode_idx() {
inline void read_mode_idx() {
eeprom_read_block(&eep, 0, 32);
eeprom_read_block(&eep, 0, 32);
while((eep[eepos] == 0xff) && (eepos < 32)) eepos++;
while((eep[eepos] == 0xff) && (eepos < 32)) eepos++;
if (eepos < 32) mode_idx = eep[eepos];//&0x10; What the?
if (eepos < 32) mode_idx = eep[eepos];//&0x10; What the?
else eepos=0;
else eepos=0;
}
}
inline void next_mode() {
inline void next_mode() {
if (mode_idx == 0 && mode_dir == -1) {
if (mode_idx == 0 && mode_dir == -1) {
// Wrap around
// Wrap around
mode_idx = mode_cnt - 1;
mode_idx = mode_cnt - 1;
} else {
} else {
mode_idx += mode_dir;
mode_idx += mode_dir;
if (mode_idx > (mode_cnt - 1)) {
if (mode_idx > (mode_cnt - 1)) {
// Wrap around
// Wrap around
mode_idx = 0;
mode_idx = 0;
}
}
}
}
}
}
inline void WDT_on() {
inline void WDT_on() {
// Setup watchdog timer to only interrupt, not reset, every 500ms.
// Setup watchdog timer to only interrupt, not reset, every 500ms.
cli(); // Disable interrupts
cli(); // Disable interrupts
wdt_reset(); // Reset the WDT
wdt_reset(); // Reset the WDT
WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
WDTCR = (1<<WDTIE) | (1<<WDP2) | (1<<WDP0); // Enable interrupt every 500ms
WDTCR = (1<<WDTIE) | (1<<WDP2) | (1<<WDP0); // Enable interrupt every 500ms
sei(); // Enable interrupts
sei(); // Enable interrupts
}
}
inline void WDT_off()
inline void WDT_off()
{
{
cli(); // Disable interrupts
cli(); // Disable interrupts
wdt_reset(); // Reset the WDT
wdt_reset(); // Reset the WDT
MCUSR &= ~(1<<WDRF); // Clear Watchdog reset flag
MCUSR &= ~(1<<WDRF); // Clear Watchdog reset flag
WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
WDTCR = 0x00; // Disable WDT
WDTCR = 0x00; // Disable WDT
sei(); // Enable interrupts
sei(); // Enable interrupts
}
}
inline void ADC_on() {
inline void ADC_on() {
ADMUX = (1 << REFS0) | (1 << ADLAR) | ADC_CHANNEL; // 1.1v reference, left-adjust, ADC1/PB2
ADMUX = (1 << REFS0) | (1 << ADLAR) | ADC_CHANNEL; // 1.1v reference, left-adjust, ADC1/PB2
DIDR0 |= (1 << ADC_DIDR); // disable digital input on ADC pin to reduce power consumption
DIDR0 |= (1 << ADC_DIDR); // disable digital input on ADC pin to reduce power consumption
ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL; // enable, start, prescale
ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL; // enable, start, prescale
}
}
inline void ADC_off() {
inline void ADC_off() {
ADCSRA &= ~(1<<7); //ADC off
ADCSRA &= ~(1<<7); //ADC off
}
}
#ifdef VOLTAGE_MON
#ifdef VOLTAGE_MON
uint8_t low_voltage(uint8_t voltage_val) {
uint8_t low_voltage(uint8_t voltage_val) {
// Start conversion
// Start conversion
ADCSRA |= (1 << ADSC);
ADCSRA |= (1 << ADSC);
// Wait for completion
// Wait for completion
while (ADCSRA & (1 << ADSC));
while (ADCSRA & (1 << ADSC));
// See if voltage is lower than what we were looking for
// See if voltage is lower than what we were looking for
if (ADCH < voltage_val) {
if (ADCH < voltage_val) {
// See if it's been low for a while
// See if it's been low for a while
if (++lowbatt_cnt > 8) {
if (++lowbatt_cnt > 8) {
lowbatt_cnt = 0;
lowbatt_cnt = 0;
return 1;
return 1;
}
}
} else {
} else {
lowbatt_cnt = 0;
lowbatt_cnt = 0;
}
}
return 0;
return 0;
}
}
#endif
#endif
ISR(WDT_vect) {
ISR(WDT_vect) {
static uint8_t ticks = 0;
static uint8_t ticks = 0;
if (ticks < 255) ticks++;
if (ticks < 255) ticks++;
if (ticks == WDT_TIMEOUT) {
if (ticks == WDT_TIMEOUT) {
if (memory) {
if (memory) {
store_mode_idx(mode_idx);
store_mode_idx(mode_idx);
} else {
} else {
// Reset the mode to the start for next time
// Reset the mode to the start for next time
store_mode_idx((mode_dir == 1) ? 0 : (mode_cnt - 1));
store_mode_idx((mode_dir == 1) ? 0 : (mode_cnt - 1));
}
}
#ifdef MODE_TURBO
#ifdef MODE_TURBO
//} else if (ticks == TURBO_TIMEOUT && modes[mode_idx] == MODE_TURBO) { // Doesn't make any sense why this doesn't work
//} else if (ticks == TURBO_TIMEOUT && modes[mode_idx] == MODE_TURBO) { // Doesn't make any sense why this doesn't work
} else if (ticks == TURBO_TIMEOUT && mode_idx == (mode_cnt - 1)) {
} else if (ticks == TURBO_TIMEOUT && mode_idx == (mode_cnt - 1)) {
// Turbo mode is always at end
// Turbo mode is always at end
PWM_LVL =185;
PWM_LVL = modes[--mode_idx];
#endif
#endif
}
}
}
}
int main(void)
int main(void)
{
{
// All ports default to input, but turn pull-up resistors on for the stars (not the ADC input! Made that mistake already)
// All ports default to input, but turn pull-up resistors on for the stars (not the ADC input! Made that mistake already)
PORTB = (1 << STAR2_PIN) | (1 << STAR3_PIN) | (1 << STAR4_PIN);
PORTB = (1 << STAR2_PIN) | (1 << STAR3_PIN) | (1 << STAR4_PIN);
// Set PWM pin to output
// Set PWM pin to output
DDRB = (1 << PWM_PIN);
DDRB = (1 << PWM_PIN);
// Set timer to do PWM for correct output pin and set prescaler timing
// Set timer to do PWM for correct output pin and set prescaler timing
TCCR0A = 0x21; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
TCCR0A = 0x23; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
// Turn features on or off as needed
// Turn features on or off as needed
#ifdef VOLTAGE_MON
#ifdef VOLTAGE_MON
ADC_on();
ADC_on();
#else
#else
ADC_off();
ADC_off();
#endif
#endif
ACSR |= (1<<7); //AC off
ACSR |= (1<<7); //AC off
// Load up the modes based on stars
// Load up the modes based on stars
// Always load up the modes array in order of lowest to highest mode
// Always load up the modes array in order of lowest to highest mode
// 0 being low for soldered, 1 for pulled-up for not soldered
// 0 being low for soldered, 1 for pulled-up for not soldered
// Moon (stock is 1 then 0)
// Moon
#ifdef MODE_MOON
#ifdef MODE_MOON
if ((PINB & (1 << STAR2_PIN))> 0) { // Stock is ==, ( > for moon default to on, soldering star will disable moon)
if ((PINB & (1 << STAR2_PIN)) == 0) {
modes[mode_cnt++] = MODE_MOON;
modes[mode_cnt++] = MODE_MOON;
}
}
#endif
#endif
#ifdef MODE_1
#ifdef MODE_LOW
modes[mode_cnt++] = MODE_1;
modes[mode_cnt++] = MODE_LOW;
#endif
#endif
#ifdef MODE_2
#ifdef MODE_MED
modes[mode_cnt++] = MODE_2;
modes[mode_cnt++] = MODE_MED;
#endif
#ifdef MODE_HIGH
modes[mode_cnt++] = MODE_HIGH;
#endif
#endif
#ifdef MODE_TURBO
#ifdef MODE_TURBO
modes[mode_cnt++] = MODE_TURBO;
modes[mode_cnt++] = MODE_TURBO;
#endif
#endif
if ((PINB & (1 << STAR3_PIN)) == 0) {
if ((PINB & (1 << STAR3_PIN)) == 0) {
// High to Low
// High to Low
mode_dir = -1;
mode_dir = -1;
} else {
} else {
mode_dir = 1;
mode_dir = 1;
}
}
// Not soldered (1) should disable memory
// Not soldered (1) should enable memory
memory = ((PINB & (1 << STAR4_PIN)) > 0 ) ? 0 : 1; //to disable momory without soldering star use ? 0: 1; (stock is ? 1 : 0;)
memory = ((PINB & (1 << STAR4_PIN)) > 0) ? 1 : 0;
// Enable sleep mode set to Idle that will be triggered by the sleep_mode() command.
// Enable sleep mode set to Idle that will be triggered by the sleep_mode() command.
// Will allow us to go idle between WDT interrupts
// Will allow us to go idle between WDT interrupts
set_sleep_mode(SLEEP_MODE_IDLE);
set_sleep_mode(SLEEP_MODE_IDLE);
// Determine what mode we should fire up
// Determine what mode we should fire up
// Read the last mode that was saved
// Read the last mode that was saved
read_mode_idx();
read_mode_idx();
if (mode_idx&0x10) {
if (mode_idx&0x10) {
// Indicates we did a short press last time, go to the next mode
// Indicates we did a short press last time, go to the next mode
// Remove short press indicator first
// Remove short press indicator first
mode_idx &= 0x0f;
mode_idx &= 0x0f;
next_mode(); // Will handle wrap arounds
next_mode(); // Will handle wrap arounds
} else {
} else {
// Didn't have a short press, keep the same mode
// Didn't have a short press, keep the same mode
}
}
// Store mode with short press indicator
// Store mode with short press indicator
store_mode_idx(mode_idx|0x10);
store_mode_idx(mode_idx|0x10);
WDT_on();
WDT_on();
// Now just fire up the mode
// Now just fire up the mode
PWM_LVL = modes[mode_idx];
PWM_LVL = modes[mode_idx];
uint8_t i = 0;
uint8_t i = 0;
uint8_t hold_pwm;
uint8_t hold_pwm;
while(1) {
while(1) {
#ifdef VOLTAGE_MON
#ifdef VOLTAGE_MON
if (low_voltage(ADC_LOW)) {
if (low_voltage(ADC_LOW)) {
// We need to go to a lower level
// We need to go to a lower level
if (mode_idx == 0 && PWM_LVL <= modes[mode_idx]) {
if (mode_idx == 0 && PWM_LVL <= modes[mode_idx]) {
// Can't go any lower than the lowest mode
// Can't go any lower than the lowest mode
// Wait until we hit the critical level before flashing 10 times and turning off
// Wait until we hit the critical level before flashing 10 times and turning off
while (!low_voltage(ADC_CRIT));
while (!low_voltage(ADC_CRIT));
i = 0;
i = 0;
while (i++<10) {
while (i++<10) {
PWM_LVL = 0;
PWM_LVL = 0;
_delay_ms(250);
_delay_ms(250);
PWM_LVL = modes[0];
PWM_LVL = modes[0];
_delay_ms(500);
_delay_ms(500);
}
}
// Turn off the light
// Turn off the light
PWM_LVL = 0;
PWM_LVL = 0;
// Disable WDT so it doesn't wake us up
// Disable WDT so it doesn't wake us up
WDT_off();
WDT_off();
// Power down as many components as possible
// Power down as many components as possible
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
sleep_mode();
} else {
} else {
// Flash 3 times before lowering
// Flash 3 times before lowering
hold_pwm = PWM_LVL;
hold_pwm = PWM_LVL;
i = 0;
i = 0;
while (i++<3) {
while (i++<3) {
PWM_LVL = 0;
PWM_LVL = 0;
_delay_ms(250);
_delay_ms(250);
PWM_LVL = hold_pwm;
PWM_LVL = hold_pwm;
_delay_ms(500);
_delay_ms(500);
}
}
// Lower the mode by half, but don't go below lowest level
// Lower the mode by half, but don't go below lowest level
if ((PWM_LVL >> 1) < modes[0]) {
if ((PWM_LVL >> 1) < modes[0]) {
PWM_LVL = modes[0];
PWM_LVL = modes[0];
mode_idx = 0;
mode_idx = 0;
} else {
} else {
PWM_LVL = (PWM_LVL >> 1);
PWM_LVL = (PWM_LVL >> 1);
}
}
// See if we should change the current mode level if we've gone under the current mode.
// See if we should change the current mode level if we've gone under the current mode.
if (PWM_LVL < modes[mode_idx]) {
if (PWM_LVL < modes[mode_idx]) {
// Lower our recorded mode
// Lower our recorded mode
mode_idx--;
mode_idx--;
}
}
}
}
// Wait 3 seconds before lowering the level again
// Wait 3 seconds before lowering the level again
_delay_ms(3000);
_delay_ms(3000);
}
}
#endif
#endif
sleep_mode();
sleep_mode();
}
}
return 0; // Standard Return Code
return 0; // Standard Return Code
}
}