Strobe Tuner Source Code

//////////////////////////////////////////////////////////////////////////////
//
// 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 件のコメント:

コメントを投稿