2
* This firmware simply helps calibrate values for voltage readings.
3
* It is not intended to be used as an actual flashlight.
5
* It will read the voltage, then read out the raw value as a series of
6
* blinks. It will provide up to three groups of blinks, representing the
7
* hundreds digit, the tens digit, then the ones. So, for a raw value of 183,
8
* it would blink once, pause, blink eight times, pause, then blink three times.
9
* It will then wait longer and re-read the voltage, then repeat.
14
* Star 4 -| |- Voltage ADC
19
* CPU speed is 4.8Mhz without the 8x divider when low fuse is 0x75
21
* define F_CPU 4800000 CPU: 4.8MHz PWM: 9.4kHz ####### use low fuse: 0x75 #######
22
* /8 PWM: 1.176kHz ####### use low fuse: 0x65 #######
23
* define F_CPU 9600000 CPU: 9.6MHz PWM: 19kHz ####### use low fuse: 0x7a #######
24
* /8 PWM: 2.4kHz ####### use low fuse: 0x6a #######
26
* Above PWM speeds are for phase-correct PWM. This program uses Fast-PWM,
27
* which when the CPU is 4.8MHz will be 18.75 kHz
30
* I use these fuse settings
37
#define F_CPU 4800000UL
40
* =========================================================================
41
* Settings to modify per driver
44
#define OWN_DELAY // Should we use the built-in delay or our own?
49
* =========================================================================
53
#include <util/delay_basic.h>
54
// Having own _delay_ms() saves some bytes AND adds possibility to use variables as input
55
static void _delay_ms(uint16_t n)
61
#include <util/delay.h>
64
#include <avr/pgmspace.h>
65
#include <avr/interrupt.h>
67
#include <avr/eeprom.h>
68
#include <avr/sleep.h>
74
#define CAP_CHANNEL 0x03 // MUX 03 corresponds with PB3 (Star 4)
75
#define CAP_DIDR ADC3D // Digital input disable bit corresponding with PB3
77
#define VOLTAGE_PIN PB2
78
#define ADC_CHANNEL 0x01 // MUX 01 corresponds with PB2
79
#define ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2
80
#define ADC_PRSCL 0x06 // clk/64
82
#define PWM_LVL OCR0B // OCR0B is the output compare register for PB1
84
inline void ADC_on() {
85
ADMUX = (1 << REFS0) | (1 << ADLAR) | ADC_CHANNEL; // 1.1v reference, left-adjust, ADC1/PB2
86
DIDR0 |= (1 << ADC_DIDR); // disable digital input on ADC pin to reduce power consumption
87
ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL; // enable, start, prescale
90
inline void ADC_off() {
91
ADCSRA &= ~(1<<7); //ADC off
94
uint8_t get_reading() {
95
// Start up ADC for capacitor pin
96
DIDR0 |= (1 << CAP_DIDR); // disable digital input on ADC pin to reduce power consumption
97
ADMUX = (1 << REFS0) | (1 << ADLAR) | CAP_CHANNEL; // 1.1v reference, left-adjust, ADC3/PB3
98
ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL; // enable, start, prescale
99
// Wait for completion
100
while (ADCSRA & (1 << ADSC));
102
// Start again as datasheet says first result is unreliable
103
ADCSRA |= (1 << ADSC);
104
// Wait for completion
105
while (ADCSRA & (1 << ADSC));
107
// just return the value
112
PWM_LVL = (BLINK_PWM>>2);
130
// Set PWM pin to output
131
DDRB = (1 << PWM_PIN);
133
// Set timer to do PWM for correct output pin and set prescaler timing
134
TCCR0A = 0x21; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
135
TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
137
// Turn features on or off as needed
139
ACSR |= (1<<7); //AC off
141
// get an average of several readings
144
for (i=0; i<8; i++) {
145
value += get_reading();
150
value = get_reading();
155
// Charge up the capacitor by setting CAP_PIN to output
156
DDRB |= (1 << CAP_PIN); // Output
157
PORTB |= (1 << CAP_PIN); // High
160
// blink once on receiving power
166
while (value >= 100) {
176
while (value >= 10) {