Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
7ebe18978This file is pinned to the selected release. Download the original to open it in your design tool.
/*
* Copyright (C) 2020 Patrick Pedersen
* 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 <https://www.gnu.org/licenses/>.
*
* Author: Patrick Pedersen <ctx.xda@gmail.com>
* Description: Main firmware routines for the Not-so-Tiny dimmer.
*
*/
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#ifdef ARDUINO_BUILD
#include <Arduino.h>
#endif
#include "config.h"
#include "input.h"
#include "strip.h"
#include "time.h"
////////////////////////
// Preprocessors
////////////////////////
#if F_CPU != 16000000L
#error "CPU clock (F_CPU) must be set to 16Mhz!"
#endif
#define MAX_BRIGHTNESS 255
#ifndef PATCH_0
#define PATCH_0 break
#endif
#ifndef PATCH_1
#define PATCH_1 break
#endif
#ifndef PATCH_2
#define PATCH_2 break
#endif
#ifndef PATCH_3
#define PATCH_3 break
#endif
#ifndef PATCH_4
#define PATCH_4 break
#endif
#ifndef PATCH_5
#define PATCH_5 break
#endif
#ifndef PATCH_6
#define PATCH_6 break
#endif
#ifndef PATCH_7
#define PATCH_7 break
#endif
#ifndef PATCH_8
#define PATCH_8 break
#endif
#ifndef PATCH_9
#define PATCH_9 break
#endif
////////////////////////
// Globals
////////////////////////
// Patches
uint8_t selected_patch;
////////////////////////
// Functions
////////////////////////
// LED Strip
/* update_strip
* ----------
* Description:
* Updates the strip for the provided patch.
* For animations, this function must be called
* repeatedly.
*/
void update_strip(uint8_t patch)
{
switch (patch) {
case 0 : {
PATCH_0;
break;
}
case 1 : {
PATCH_1;
break;
}
case 2 : {
PATCH_2;
break;
}
case 3 : {
PATCH_3;
break;
}
case 4 : {
PATCH_4;
break;
}
case 5 : {
PATCH_5;
break;
}
case 6 : {
PATCH_6;
break;
}
case 7 : {
PATCH_7;
break;
}
case 8 : {
PATCH_8;
break;
}
case 9 : {
PATCH_9;
break;
}
case 10 : {
PATCH_10;
break;
}
case 11 : {
PATCH_11;
break;
}
case 12 : {
PATCH_12;
break;
}
case 13 : {
PATCH_13;
break;
}
case 14 : {
PATCH_14;
break;
}
case 15 : {
PATCH_15;
break;
}
case 16 : {
PATCH_16;
break;
}
case 17 : {
PATCH_17;
break;
}
// case 18 : {
// PATCH_18;
// break;
// }
// case 19 : {
// PATCH_19;
// break;
// }
default: {
break;
}
}
}
////////////////////////
// Main routine
////////////////////////
void _main() {
DELAY_MS(10); // Allow supply voltage to calm down
// Calibration
#if STRIP_TYPE == WS2812
strip_size = GET_STRIP_SIZE;
if (strip_size == 0)
strip_calibrate();
#endif
// Patches
selected_patch = 0;
update_strip(selected_patch);
// Main loop
bool prev_btn_state = BTN_STATE;
bool calibrated = false;
while(true) {
bool btn_state = BTN_STATE;
if (!prev_btn_state && btn_state) { // Button press
#if defined(BTN_DEBOUNCE_TIME) && BTN_DEBOUNCE_TIME > 0
DELAY_MS(BTN_DEBOUNCE_TIME);
#endif
#if STRIP_TYPE == WS2812
reset_timer();
#endif
}
#if STRIP_TYPE == WS2812 && !defined(STRIP_SIZE)
else if (btn_state) {
if (ms_passed() >= 5000) {
strip_calibrate();
calibrated = true;
}
continue;
}
#endif
else if (prev_btn_state && !btn_state) { // Button Released
if (calibrated) {
calibrated = false;
} else {
selected_patch = (selected_patch + 1) % NUM_PATCHES;
update_strip(selected_patch);
}
}
prev_btn_state = btn_state;
update_strip(selected_patch);
}
}
////////////////////////
// Initialization
////////////////////////
#ifdef ARDUINO_BUILD
void setup() {
Serial.begin(9600);
pinMode(WS2812_DIN, OUTPUT);
pinMode(BTN, INPUT_PULLUP);
#ifndef BRIGHTNESS_POT_MISSING
pinMode(BRIGHTNESS_POT, INPUT);
#endif
}
void loop() {
_main();
}
#else
/* main
* ----
* Description:
* The dimmer firmware main routine.
*/
int main()
{
// Initialization
// Timer 0
TCCR0B |= (1 << CS00); // No prescaling
#if defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
TIMSK0 |= (1 << TOIE0); // Enable Timer interrupts
TIFR0 |= (1 << TOV0); // Interrupt on timer overflow
#else
TIMSK |= (1 << TOIE0); // Enable Timer interrupts
TIFR |= (1 << TOV0); // Interrupt on timer overflow
#endif
#if STRIP_TYPE == NON_ADDR
DDRB |= (1 << PB0) | (1 << PB1) | (1 << PB4);
// Enable Fast PWM
TCCR0A |= (1 << WGM01) | (1 << WGM00);
TCCR0B |= (0 << WGM02);
TCCR0A |= (1 << COM0A1) | (0 << COM0A0) // Non-Inverting PWM on OCR0A/PB0
| (1 << COM0B1) | (0 << COM0B1); // Non-Inverting PWM on OCR0B/PB1
OCR0A = 0;
OCR0B = 0;
// Timer 1
PLLCSR |= (1 << PLLE); // Enable PLL (64 MHz)
PLLCSR |= (1 << PCKE); // Use PLL as timer clock source
TCCR1 |= (1 << CS10); // 1024 Prescaler
GTCCR |= (1 << PWM1B)
| (1 << COM1B1) | (0 << COM1B0); // Non-Inverting PWM on OCR1B/PB4
TCCR1 |= (1 << COM1A0);
OCR1B = 0;
OCR1C = 255;
#endif
// Pins
#if STRIP_TYPE == WS2812
DDRB |= WS2812_DIN_MSK; // Set WS2812 Data input pin to output
#endif
DDRB &= ~(1 << BTN); // Set button pin to input
PORTB |= (1 << BTN); // Enable internal pull-up on Button pin
DDRB &= ~(1 << GATE); // Set GATE jack to input
// ADC
ADMUX = (1 << ADLAR); // Reduce ADC input to 8-bit value (0-255)
#if defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
ADMUX |= (1 << REFS0); // Set reference to AVcc
#endif
#ifndef BRIGHTNESS_POT_MISSING
ADMUX |= BRIGHTNESS_POT_ADMUX_MSK; // Set MUX to Brightness potentiometer pin
#endif
ADCSRA =
(1 << ADEN) | // Enable ADC
(1 << ADSC) | // Start first conversion
(1 << ADPS2) | // set prescaler to 128, bit 2
(1 << ADPS1) | // set prescaler to 128, bit 1
(1 << ADPS0); // set prescaler to 128, bit 0
sei();
_main();
}
#endif