summaryrefslogtreecommitdiff
path: root/picl-firmware/fan_control.c
diff options
context:
space:
mode:
Diffstat (limited to 'picl-firmware/fan_control.c')
-rw-r--r--picl-firmware/fan_control.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/picl-firmware/fan_control.c b/picl-firmware/fan_control.c
new file mode 100644
index 0000000..9e87963
--- /dev/null
+++ b/picl-firmware/fan_control.c
@@ -0,0 +1,86 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/sleep.h>
+
+void setup_adc() {
+ //enable interrupts
+ sei();
+ // setup external reference voltage.
+ ADMUX &= ~(3UL << REFS0);
+ ADMUX |= (1UL << REFS0);
+ // set left adjusted ADC result so we can easily only use the upper 8 bits of the result
+ ADCSRB |= (1UL << ADLAR);
+ // enable ADC interrupt
+ ADCSRA |= (1UL << ADIE);
+}
+
+void setup_timers() {
+ //use system clock for timers, no prescaler.
+ TCCR0B &= ~(7UL << CS00);
+ TCCR0B |= (1UL << CS00);
+
+ //set mode 5 (PWM, phase correct, top defined by OCRA)
+ TCCR0A &= ~(3UL << WGM00);
+ TCCR0B &- ~(1UL << WGM02);
+ TCCR0A |= (1UL << WGM00);
+ TCCR0B |= (1UL << WGM02);
+}
+
+void enable_ADC() {
+ PRR &= ~(1UL << PRADC);
+ ADCSRA |= (1UL << ADEN);
+}
+
+void disable_ADC() {
+ ADCSRA &= ~(1UL << ADEN);
+ PRR |= (1UL << PRADC);
+}
+
+void select_ADC_channel(int channel) {
+ ADMUX &= ~(7UL << MUX0);
+ ADMUX |= (channel << MUX0);
+}
+
+uint8_t get_ADC_result() {
+ uint8_t result = ADCL;
+ //conversion would be blocked if we don't also read ADCH although we won't use the upper 2 bits.
+ uint8_t unblock = ADCH;
+ return result;
+}
+
+void start_ADC() {
+ ADCSRA |= (1UL << ADSC);
+}
+
+volatile uint8_t fan1;
+volatile uint8_t fan2;
+
+void start_polling_fans() {
+ PRR &= ~(1UL << PRADC);
+ enable_ADC();
+ select_ADC_channel(ADC1D);
+ start_ADC();
+}
+
+ISR(ADC_vect) {
+ if(ADMUX & (7UL << MUX0) == ADC1D) {
+ fan1 = get_ADC_result();
+ select_ADC_channel(ADC2D);
+ start_ADC();
+ return;
+ }
+
+ if(ADMUX & (7UL << MUX0) == ADC2D) {
+ fan2 = get_ADC_result();
+ disable_ADC();
+ return;
+ }
+}
+
+int main() {
+ set_sleep_mode(0);
+ setup_adc();
+ setup_timers();
+
+ while(1);
+}