aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSelene ToyKeeper2015-10-05 16:57:11 -0600
committerSelene ToyKeeper2015-10-05 16:57:11 -0600
commit58e82f12f2ac26c764439cbb06e2d7ffb5396c6b (patch)
treef2a1dab74241f69bb3ce7646fad518186312ced9
parentmerged trunk (diff)
parentAdded volts+tenths and 8-bar battery check styles. (diff)
downloadanduril-58e82f12f2ac26c764439cbb06e2d7ffb5396c6b.tar.gz
anduril-58e82f12f2ac26c764439cbb06e2d7ffb5396c6b.tar.bz2
anduril-58e82f12f2ac26c764439cbb06e2d7ffb5396c6b.zip
merged tiny25 branch
-rwxr-xr-xbin/level_calc.py28
-rw-r--r--tk-attiny.h91
-rw-r--r--tk-calibration.h82
-rw-r--r--tk-delay.h51
-rw-r--r--tk-voltage.h153
5 files changed, 399 insertions, 6 deletions
diff --git a/bin/level_calc.py b/bin/level_calc.py
index d45e5bc..63926ba 100755
--- a/bin/level_calc.py
+++ b/bin/level_calc.py
@@ -43,13 +43,13 @@ def main(args):
def single_pwm(v):
"""Estimate the PWM levels for a one-channel driver."""
- visual_min = math.pow(v['lm_min'], 1.0/3)
- visual_max = math.pow(v['lm_max'], 1.0/3)
+ visual_min = invpower(v['lm_min'])
+ visual_max = invpower(v['lm_max'])
step_size = (visual_max - visual_min) / (v['num_levels']-1)
modes = []
goal = visual_min
for i in range(v['num_levels']):
- goal_lm = goal**3
+ goal_lm = power(goal)
#pwm_float = ((goal_lm / v['lm_max']) * (256-v['pwm_min'])) + v['pwm_min'] - 1
pwm_float = (((goal_lm-v['lm_min']) / (v['lm_max']-v['lm_min'])) \
* (255-v['pwm_min'])) \
@@ -66,13 +66,15 @@ def dual_pwm(v):
"""Estimate the PWM levels for a two-channel driver.
Assume the first channel is the brighter one, and second will be used for moon/low modes.
"""
- visual_min = math.pow(v['lm2_min'], 1.0/3)
- visual_max = math.pow(v['lm_max'], 1.0/3)
+ #visual_min = math.pow(v['lm2_min'], 1.0/power)
+ #visual_max = math.pow(v['lm_max'], 1.0/power)
+ visual_min = invpower(v['lm2_min'])
+ visual_max = invpower(v['lm_max'])
step_size = (visual_max - visual_min) / (v['num_levels']-1)
modes = []
goal = visual_min
for i in range(v['num_levels']):
- goal_lm = goal**3
+ goal_lm = power(goal)
# Up to the second channel's limit, calculate things just like a
# single-channel driver (first channel will be zero)
if goal_lm <= v['lm2_max']:
@@ -125,6 +127,20 @@ def get_value(text, default, args):
result = result.strip()
return result
+def power(x):
+ #return x**5
+ return x**3
+ #return x**2
+ #return math.e**x
+ #return 2.0**x
+
+def invpower(x):
+ #return math.pow(x, 1/5.0)
+ return math.pow(x, 1/3.0)
+ #return math.pow(x, 1/2.0)
+ #return math.log(x, math.e)
+ #return math.log(x, 2.0)
+
if __name__ == "__main__":
import sys
main(sys.argv[1:])
diff --git a/tk-attiny.h b/tk-attiny.h
new file mode 100644
index 0000000..9415a97
--- /dev/null
+++ b/tk-attiny.h
@@ -0,0 +1,91 @@
+#ifndef TK_ATTINY_H
+#define TK_ATTINY_H
+/*
+ * Attiny portability header.
+ * This helps abstract away the differences between various attiny MCUs.
+ *
+ * Copyright (C) 2015 Selene ToyKeeper
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+// Choose your MCU here, or in the main .c file, or in the build script
+//#define ATTINY 13
+//#define ATTINY 25
+
+/******************** hardware-specific values **************************/
+#if (ATTINY == 13)
+ #define F_CPU 4800000UL
+ #define EEPSIZE 64
+ #define V_REF REFS0
+ #define BOGOMIPS 950
+#elif (ATTINY == 25)
+ // TODO: Use 6.4 MHz instead of 8 MHz?
+ #define F_CPU 8000000UL
+ #define EEPSIZE 128
+ #define V_REF REFS1
+ #define BOGOMIPS 2000
+#else
+ Hey, you need to define ATTINY.
+#endif
+
+
+/******************** I/O pin and register layout ************************/
+#ifdef FET_7135_LAYOUT
+/*
+ * ----
+ * Reset -|1 8|- VCC
+ * OTC -|2 7|- Voltage ADC
+ * Star 3 -|3 6|- PWM (FET)
+ * GND -|4 5|- PWM (1x7135)
+ * ----
+ */
+
+#define STAR2_PIN PB0 // If this pin isn't used for ALT_PWM
+#define STAR3_PIN PB4 // pin 3
+
+#define CAP_PIN PB3 // pin 2, OTC
+#define CAP_CHANNEL 0x03 // MUX 03 corresponds with PB3 (Star 4)
+#define CAP_DIDR ADC3D // Digital input disable bit corresponding with PB3
+
+#define PWM_PIN PB1 // pin 6, FET PWM
+#define PWM_LVL OCR0B // OCR0B is the output compare register for PB1
+#define ALT_PWM_PIN PB0 // pin 5, 1x7135 PWM
+#define ALT_PWM_LVL OCR0A // OCR0A is the output compare register for PB0
+
+#define VOLTAGE_PIN PB2 // pin 7, voltage ADC
+#define ADC_CHANNEL 0x01 // MUX 01 corresponds with PB2
+#define ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2
+#define ADC_PRSCL 0x06 // clk/64
+
+#endif // FET_7135_LAYOUT
+
+#ifdef FERRERO_ROCHER_LAYOUT
+/*
+ * ----
+ * Reset -|1 8|- VCC
+ * E-switch -|2 7|- Voltage ADC
+ * Red LED -|3 6|- PWM
+ * GND -|4 5|- Green LED
+ * ----
+ */
+// TODO: fill in this section, update Ferrero_Rocher code to use it.
+#endif // FERRERO_ROCHER_LAYOUT
+
+#ifndef PWM_LVL
+ Hey, you need to define an I/O pin layout.
+#endif
+
+#endif // TK_ATTINY_H
diff --git a/tk-calibration.h b/tk-calibration.h
new file mode 100644
index 0000000..2b5ff9f
--- /dev/null
+++ b/tk-calibration.h
@@ -0,0 +1,82 @@
+#ifndef TK_CALIBRATION_H
+#define TK_CALIBRATION_H
+/*
+ * Attiny calibration header.
+ * This allows using a single set of hardcoded values across multiple projects.
+ *
+ * Copyright (C) 2015 Selene ToyKeeper
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/********************** Voltage ADC calibration **************************/
+// These values were measured using RMM's FET+7135.
+// See battcheck/readings.txt for reference values.
+// the ADC values we expect for specific voltages
+#define ADC_44 205
+#define ADC_43 201
+#define ADC_42 196
+#define ADC_41 191
+#define ADC_40 187
+#define ADC_39 182
+#define ADC_38 177
+#define ADC_37 172
+#define ADC_36 168
+#define ADC_35 163
+#define ADC_34 158
+#define ADC_33 153
+#define ADC_32 149
+#define ADC_31 144
+#define ADC_30 139
+#define ADC_29 134
+#define ADC_28 130
+#define ADC_27 125
+#define ADC_26 120
+#define ADC_25 116
+#define ADC_24 111
+#define ADC_23 106
+#define ADC_22 101
+#define ADC_21 97
+#define ADC_20 92
+
+#define ADC_100p ADC_42 // the ADC value for 100% full (resting)
+#define ADC_75p ADC_40 // the ADC value for 75% full (resting)
+#define ADC_50p ADC_38 // the ADC value for 50% full (resting)
+#define ADC_25p ADC_35 // the ADC value for 25% full (resting)
+#define ADC_0p ADC_30 // the ADC value for 0% full (resting)
+#define ADC_LOW ADC_28 // When do we start ramping down
+#define ADC_CRIT ADC_27 // When do we shut the light off
+
+
+/********************** Offtime capacitor calibration ********************/
+// Values are between 1 and 255, and can be measured with offtime-cap.c
+// See battcheck/otc-readings.txt for reference values.
+// These #defines are the edge boundaries, not the center of the target.
+#ifdef OFFTIM3
+// The OTC value 0.5s after being disconnected from power
+// (anything higher than this is a "short press")
+#define CAP_SHORT 190
+// The OTC value 1.5s after being disconnected from power
+// Between CAP_MED and CAP_SHORT is a "medium press"
+#define CAP_MED 94
+// Below CAP_MED is a long press
+#else
+// The OTC value 1.0s after being disconnected from power
+// Anything higher than this is a short press, lower is a long press
+#define CAP_SHORT 115
+#endif
+
+
+#endif // TK_CALIBRATION_H
diff --git a/tk-delay.h b/tk-delay.h
new file mode 100644
index 0000000..57bdded
--- /dev/null
+++ b/tk-delay.h
@@ -0,0 +1,51 @@
+#ifndef TK_DELAY_H
+#define TK_DELAY_H
+/*
+ * Smaller, more flexible replacement(s) for default _delay_ms() functions.
+ *
+ * Copyright (C) 2015 Selene ToyKeeper
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef OWN_DELAY
+#include "tk-attiny.h"
+#include <util/delay_basic.h>
+// Having own _delay_ms() saves some bytes AND adds possibility to use variables as input
+void _delay_ms(uint16_t n)
+{
+ // TODO: make this take tenths of a ms instead of ms,
+ // for more precise timing?
+ #ifdef USE_FINE_DELAY
+ if (n==0) { _delay_loop_2(BOGOMIPS/3); }
+ else {
+ while(n-- > 0) _delay_loop_2(BOGOMIPS);
+ }
+ #else
+ while(n-- > 0) _delay_loop_2(BOGOMIPS);
+ #endif
+}
+#ifdef USE_DELAY_S
+void _delay_s() // because it saves a bit of ROM space to do it this way
+{
+ _delay_ms(1000);
+}
+#endif
+#else
+#include <util/delay.h>
+#endif
+
+
+#endif // TK_DELAY_H
diff --git a/tk-voltage.h b/tk-voltage.h
new file mode 100644
index 0000000..5eaf0d4
--- /dev/null
+++ b/tk-voltage.h
@@ -0,0 +1,153 @@
+#ifndef TK_VOLTAGE_H
+#define TK_VOLTAGE_H
+/*
+ * Voltage / battcheck functions.
+ *
+ * Copyright (C) 2015 Selene ToyKeeper
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "tk-attiny.h"
+#include "tk-calibration.h"
+
+#ifdef VOLTAGE_MON
+inline void ADC_on() {
+ // disable digital input on ADC pin to reduce power consumption
+ DIDR0 |= (1 << ADC_DIDR);
+ // 1.1v reference, left-adjust, ADC1/PB2
+ ADMUX = (1 << V_REF) | (1 << ADLAR) | ADC_CHANNEL;
+ // enable, start, prescale
+ ADCSRA = (1 << ADEN ) | (1 << ADSC ) | ADC_PRSCL;
+}
+
+uint8_t get_voltage() {
+ // Start conversion
+ ADCSRA |= (1 << ADSC);
+ // Wait for completion
+ while (ADCSRA & (1 << ADSC));
+ // Send back the result
+ return ADCH;
+}
+#else
+inline void ADC_off() {
+ ADCSRA &= ~(1<<7); //ADC off
+}
+#endif
+
+#ifdef USE_BATTCHECK
+#ifdef BATTCHECK_4bars
+PROGMEM const uint8_t voltage_blinks[] = {
+ // 0 blinks for less than 1%
+ ADC_0p, // 1 blink for 1%-25%
+ ADC_25p, // 2 blinks for 25%-50%
+ ADC_50p, // 3 blinks for 50%-75%
+ ADC_75p, // 4 blinks for 75%-100%
+ ADC_100p, // 5 blinks for >100%
+ 255, // Ceiling, don't remove (6 blinks means "error")
+};
+#endif // BATTCHECK_4bars
+#ifdef BATTCHECK_8bars
+PROGMEM const uint8_t voltage_blinks[] = {
+ // 0 blinks for less than 1%
+ ADC_30, // 1 blink for 1%-12.5%
+ ADC_33, // 2 blinks for 12.5%-25%
+ ADC_35, // 3 blinks for 25%-37.5%
+ ADC_37, // 4 blinks for 37.5%-50%
+ ADC_38, // 5 blinks for 50%-62.5%
+ ADC_39, // 6 blinks for 62.5%-75%
+ ADC_40, // 7 blinks for 75%-87.5%
+ ADC_41, // 8 blinks for 87.5%-100%
+ ADC_42, // 9 blinks for >100%
+ 255, // Ceiling, don't remove (10 blinks means "error")
+};
+#endif // BATTCHECK_8bars
+#ifdef BATTCHECK_VpT
+/*
+PROGMEM const uint8_t v_whole_blinks[] = {
+ // 0 blinks for (shouldn't happen)
+ 0, // 1 blink for (shouldn't happen)
+ ADC_20, // 2 blinks for 2V
+ ADC_30, // 3 blinks for 3V
+ ADC_40, // 4 blinks for 4V
+ 255, // Ceiling, don't remove
+};
+PROGMEM const uint8_t v_tenth_blinks[] = {
+ // 0 blinks for less than 1%
+ ADC_30,
+ ADC_33,
+ ADC_35,
+ ADC_37,
+ ADC_38,
+ ADC_39,
+ ADC_40,
+ ADC_41,
+ ADC_42,
+ 255, // Ceiling, don't remove
+};
+*/
+PROGMEM const uint8_t voltage_blinks[] = {
+ // 0 blinks for (shouldn't happen)
+ ADC_25,(2<<5)+5,
+ ADC_26,(2<<5)+6,
+ ADC_27,(2<<5)+7,
+ ADC_28,(2<<5)+8,
+ ADC_29,(2<<5)+9,
+ ADC_30,(3<<5)+0,
+ ADC_31,(3<<5)+1,
+ ADC_32,(3<<5)+2,
+ ADC_33,(3<<5)+3,
+ ADC_34,(3<<5)+4,
+ ADC_35,(3<<5)+5,
+ ADC_36,(3<<5)+6,
+ ADC_37,(3<<5)+7,
+ ADC_38,(3<<5)+8,
+ ADC_39,(3<<5)+9,
+ ADC_40,(4<<5)+0,
+ ADC_41,(4<<5)+1,
+ ADC_42,(4<<5)+2,
+ ADC_43,(4<<5)+3,
+ ADC_44,(4<<5)+4,
+ 255, (1<<5)+1, // Ceiling, don't remove
+};
+inline uint8_t battcheck() {
+ // Return an composite int, number of "blinks", for approximate battery charge
+ // Uses the table above for return values
+ // Return value is 3 bits of whole volts and 5 bits of tenths-of-a-volt
+ uint8_t i, voltage;
+ voltage = get_voltage();
+ // figure out how many times to blink
+ for (i=0;
+ voltage > pgm_read_byte(voltage_blinks + i);
+ i += 2) {}
+ return pgm_read_byte(voltage_blinks + i + 1);
+}
+#else // #ifdef BATTCHECK_VpT
+inline uint8_t battcheck() {
+ // Return an int, number of "blinks", for approximate battery charge
+ // Uses the table above for return values
+ uint8_t i, voltage;
+ voltage = get_voltage();
+ // figure out how many times to blink
+ for (i=0;
+ voltage > pgm_read_byte(voltage_blinks + i);
+ i ++) {}
+ return i;
+}
+#endif // BATTCHECK_VpT
+#endif
+
+
+#endif // TK_VOLTAGE_H
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions. For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage. In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.