//
// Project : Strobe Tuner
//
// Programmed by ota957(c)
//
// MPU = ATmega168P
// F_CPU = 20MHz(Xtal OSC Module)
// Lfuse = 0xF0(CKDIV8 disable, BOD Reset, External Clock)
// Hfuse = 0xDF(default)
// Efuse = 0xD9(default)
//
//////////////////////////////////////////////////////////////////////////////
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#define _SBI(p, q) ((p) |= _BV(q))
#define _CBI(p, q) ((p) &= ~_BV(q))
//////////////////////////////////////////////////////////////////////////////
// グローバル変数及び各定義
//////////////////////////////////////////////////////////////////////////////
#define SEG_0 0b00111111
#define SEG_1 0b00000110
#define SEG_2 0b01011011
#define SEG_3 0b01001111
#define SEG_4 0b01100110
#define SEG_5 0b01101101
#define SEG_6 0b01111101
#define SEG_7 0b00000111
#define SEG_8 0b01111111
#define SEG_9 0b01100111
#define SEG_A 0b01110111
#define SEG_B 0b01111100
#define SEG_C 0b00111001
#define SEG_D 0b01011110
#define SEG_E 0b01111001
#define SEG_F 0b01110001
#define SEG_G /*0b01101111*/0b00111101
#define SEG_m 0b01000000
#define SEG_OFF 0b00000000
#define DIMMER_MAX /*8*/16
#define DIMMER_DIG1 (uint8_t)(DIMMER_MAX * 0.35)
#define DIMMER_DIG2 DIMMER_DIG1
/******** LED M7-M1 & L1-L7 Pattern ********/
typedef struct{
uint8_t uMData;
uint8_t uLData;
uint8_t uMDimmer;
uint8_t uLDimmer;
} M17L17PATTERN;
M17L17PATTERN arM17L17PATTERN[] = {
{0b00000001, 0b00000000, (uint8_t)(DIMMER_MAX * 1.0), (uint8_t)(DIMMER_MAX * 0.0)},
{0b00000010, 0b00000000, (uint8_t)(DIMMER_MAX * 1.0), (uint8_t)(DIMMER_MAX * 0.0)},
{0b00000100, 0b00000000, (uint8_t)(DIMMER_MAX * 1.0), (uint8_t)(DIMMER_MAX * 0.0)},
{0b00001000, 0b00000000, (uint8_t)(DIMMER_MAX * 0.7), (uint8_t)(DIMMER_MAX * 0.0)},
{0b00010000, 0b00000000, (uint8_t)(DIMMER_MAX * 0.7), (uint8_t)(DIMMER_MAX * 0.0)},
{0b00100000, 0b00000000, (uint8_t)(DIMMER_MAX * 0.5), (uint8_t)(DIMMER_MAX * 0.0)},
{0b01000000, 0b00000000, (uint8_t)(DIMMER_MAX * 0.5), (uint8_t)(DIMMER_MAX * 0.0)},
{0b00000000, 0b01000000, (uint8_t)(DIMMER_MAX * 0.0), (uint8_t)(DIMMER_MAX * 0.5)},
{0b00000000, 0b00100000, (uint8_t)(DIMMER_MAX * 0.0), (uint8_t)(DIMMER_MAX * 0.5)},
{0b00000000, 0b00010000, (uint8_t)(DIMMER_MAX * 0.0), (uint8_t)(DIMMER_MAX * 0.7)},
{0b00000000, 0b00001000, (uint8_t)(DIMMER_MAX * 0.0), (uint8_t)(DIMMER_MAX * 0.7)},
{0b00000000, 0b00000100, (uint8_t)(DIMMER_MAX * 0.0), (uint8_t)(DIMMER_MAX * 1.0)},
{0b00000000, 0b00000010, (uint8_t)(DIMMER_MAX * 0.0), (uint8_t)(DIMMER_MAX * 1.0)},
{0b00000000, 0b00000001, (uint8_t)(DIMMER_MAX * 0.0), (uint8_t)(DIMMER_MAX * 1.0)}
};
#define ELEMENTS_M17L17 sizeof(arM17L17PATTERN) / sizeof(arM17L17PATTERN[0])
volatile uint16_t uTIMERCOUNT;
volatile uint8_t uMASK = 0x06;
/********* Scale Table ********/
typedef struct {
uint8_t uLName;
uint8_t uRName;
uint16_t uTimer;
} SCALETABLE;
const SCALETABLE arSCALETABLE[] PROGMEM = {
{SEG_1, SEG_E, (uint16_t)((double)F_CPU / ((double)ELEMENTS_M17L17 * 41.203)) - 1},
{SEG_1, SEG_A, (uint16_t)((double)F_CPU / ((double)ELEMENTS_M17L17 * 55.000)) - 1},
{SEG_2, SEG_D, (uint16_t)((double)F_CPU / ((double)ELEMENTS_M17L17 * 73.416)) - 1},
{SEG_2, SEG_E, (uint16_t)((double)F_CPU / ((double)ELEMENTS_M17L17 * 82.407)) - 1},
{SEG_2, SEG_G, (uint16_t)((double)F_CPU / ((double)ELEMENTS_M17L17 * 97.999)) - 1},
{SEG_2, SEG_A, (uint16_t)((double)F_CPU / ((double)ELEMENTS_M17L17 * 110.000)) - 1},
{SEG_3, SEG_D, (uint16_t)((double)F_CPU / ((double)ELEMENTS_M17L17 * 146.832)) - 1},
{SEG_3, SEG_G, (uint16_t)((double)F_CPU / ((double)ELEMENTS_M17L17 * 195.998)) - 1},
{SEG_3, SEG_B, (uint16_t)((double)F_CPU / ((double)ELEMENTS_M17L17 * 246.942)) - 1},
{SEG_4, SEG_E, (uint16_t)((double)F_CPU / ((double)ELEMENTS_M17L17 * 329.628)) - 1}
};
#define ELEMENTS_SCALETABLE sizeof(arSCALETABLE) / sizeof(arSCALETABLE[0])
/******** LED DriveData ********/
typedef struct {
uint8_t uAnode;
uint8_t uKathode;
uint8_t uDimmer;
} LEDDRVDATA;
LEDDRVDATA arLEDDRVDATA[] = {
{0x01, 0 /* dummy */, 0 /* dummy */},
{0x02, SEG_1, DIMMER_DIG1},
{0x04, SEG_E, DIMMER_DIG2},
{0x08, 0 /* dummy */, 0 /* dummy */}
};
#define ELEMENTS_LEDDRVDATA sizeof(arLEDDRVDATA) / sizeof(arLEDDRVDATA[0])
#define POS_M1M7 0
#define POS_DIG1 1
#define POS_DIG2 2
#define POS_L1L7 3
#define SW_ON 0
#define SW_OFF 1
volatile uint8_t uREQUEST = SW_OFF;
//////////////////////////////////////////////////////////////////////////////
// 各割り込み処理
//////////////////////////////////////////////////////////////////////////////
// ---------------------------------------------------------------------------
// タイマー1 比較一致割り込み
// ---------------------------------------------------------------------------
ISR(TIMER1_COMPA_vect)
{
static uint8_t uPosition = 0;
uPosition %= ELEMENTS_M17L17;
arLEDDRVDATA[POS_M1M7].uKathode = arM17L17PATTERN[uPosition].uMData;
arLEDDRVDATA[POS_L1L7].uKathode = arM17L17PATTERN[uPosition].uLData;
arLEDDRVDATA[POS_M1M7].uDimmer = arM17L17PATTERN[uPosition].uMDimmer;
arLEDDRVDATA[POS_L1L7].uDimmer = arM17L17PATTERN[uPosition++].uLDimmer;
}
// ---------------------------------------------------------------------------
// タイマー0 比較一致割り込み
// ---------------------------------------------------------------------------
ISR(TIMER0_COMPA_vect, ISR_NOBLOCK)
{
// Switch detect
if(bit_is_clear(PINB, PINB1))
uREQUEST = SW_ON;
else
uREQUEST = SW_OFF;
uTIMERCOUNT++;
}
//////////////////////////////////////////////////////////////////////////////
// メインループ
//////////////////////////////////////////////////////////////////////////////
int main(void)
{
static uint8_t uScaleIndex = 0;
/******** I/O Setting ********/
_SBI(PORTB, PB0); // PB0 Input & Pullup
_SBI(PORTB, PB1); // PB1 Input & Pullup
_SBI(DDRB, DDB2); // PB2 Output
DDRC = 0b00001111; // PC0-3 Output
_SBI(PORTB, PB3); // PB3-5 Input & Pullup
_SBI(PORTB, PB4); // ↑
_SBI(PORTB, PB5); // ↑
_SBI(PORTB, PB7); // PB7 Input & Pullup(NC Pin)
_SBI(PORTC, PC4); // PC4 Input & Pullup(↑)
_SBI(PORTC, PC5); // PC5 Input & Pullup(↑)
/******** Timer1 Setting ********/
_SBI(TCCR1B, WGM12); // TIMER1 CTCMode
_SBI(TCCR1B, CS10); // TIMER1 Prescaler = 1/1
OCR1A = pgm_read_word(&(arSCALETABLE[uScaleIndex].uTimer));
_SBI(TIMSK1, OCIE1A); // TIMER1 CTC Interrut Enable
/******** Timer0 Setting ********/
_SBI(TCCR0A, WGM01); // TIMER0 CTCMode
_SBI(TCCR0B, CS00); // TIMER0 Prescaler = 1/1024
_SBI(TCCR0B, CS02); // ↑
OCR0A = (uint8_t)(F_CPU * 10E-3 / 1024);
_SBI(TIMSK0, OCIE0A); // TIMER0 CTC Interrut Enable
/******** Analog Comparator Setting ********/
_SBI(ACSR, ACBG); // Apply Bandgap Ref
_SBI(DIDR1, AIN1D); // Disable AIN1 digital Input
/******** Enable all interrupts ********/
sei();
/******** Set DIG1-DIG2 Initial Data ********/
arLEDDRVDATA[POS_DIG1].uKathode = pgm_read_byte(&(arSCALETABLE[uScaleIndex].uLName));
arLEDDRVDATA[POS_DIG2].uKathode = pgm_read_byte(&(arSCALETABLE[uScaleIndex].uRName));
arLEDDRVDATA[POS_DIG1].uDimmer = DIMMER_DIG1;
arLEDDRVDATA[POS_DIG2].uDimmer = DIMMER_DIG2;
uint8_t uStrobeMask = 0xff;
/******** Main Loop ********/
while(1){
/******** Input Signal Capture & Batt Check ********/
if(bit_is_set(PINB, PINB0))
uStrobeMask = 0xff;
else
uStrobeMask = (arLEDDRVDATA[POS_DIG1].uAnode | arLEDDRVDATA[POS_DIG2].uAnode);
if(uStrobeMask == 0xff && bit_is_clear(ACSR, ACO))
_SBI(PORTB, PB2);
else
_CBI(PORTB, PB2);
/******** LED Scan & Display ********/
static uint8_t uAnodeIndex = 0;
static uint8_t uDimmerCount = DIMMER_MAX;
uint8_t uAnodeScan, uKathodeData, uDimmerSet;
if(++uDimmerCount > DIMMER_MAX){
/*DDRC*/PORTC = 0x00;
DDRD = 0x00;
uAnodeIndex %= ELEMENTS_LEDDRVDATA;
uAnodeScan = arLEDDRVDATA[uAnodeIndex].uAnode;
uKathodeData = arLEDDRVDATA[uAnodeIndex].uKathode;
uDimmerSet = arLEDDRVDATA[uAnodeIndex++].uDimmer;
uDimmerCount = 1;
}else{
DDRD = (uDimmerCount < uDimmerSet) ? uKathodeData : 0x00;
/*DDRC*/PORTC = uAnodeScan & uStrobeMask;
}
/******** ScaleTable Select ********/
if(uREQUEST == SW_ON && uTIMERCOUNT >= 45){
uScaleIndex = (uScaleIndex + 1 < ELEMENTS_SCALETABLE) ? uScaleIndex + 1 : 0;
arLEDDRVDATA[POS_DIG1].uKathode = pgm_read_byte(&(arSCALETABLE[uScaleIndex].uLName));
arLEDDRVDATA[POS_DIG2].uKathode = pgm_read_byte(&(arSCALETABLE[uScaleIndex].uRName));
OCR1A = pgm_read_word(&(arSCALETABLE[uScaleIndex].uTimer));
uTIMERCOUNT = 0;
}
}
}
0 件のコメント:
コメントを投稿