/************************************************************
device: tiny2313
clk: 8MHz
written by yosio @ chocolatespeaker
2010/1/9
*************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#define WAVEFORM_SIN 0 //正弦波
#define WAVEFORM_PULSE 1 //矩形波
#define WAVEFORM_SAW 2 //ノコギリ波
#define WAVEFORM_SAW_R 3 //逆ノコギリ波
#define LED_FLIP PIND|=0b01000000;
/*グローバル変数宣言*/
uint8_t cnt_wave=1; //波形生成カウンタ
uint8_t wave[64]={0}; //波形データ
const uint8_t data_sin[] PROGMEM ={128,140,153,165,177,188,
199,209,218,226,234,240,
245,250,253,254,255};
const uint16_t data_freq[] PROGMEM={62500,31250,15625,12500,
6250,2500,1786,1250,625,
250,179,125,50,25,18,13};
/*プロトタイプ宣言*/
uint8_t getSW(uint8_t *);
void changeWave(uint8_t);
uint8_t reversalBits(uint8_t);
/*カウンタ1の割り込み*/
ISR(TIMER1_COMPA_vect){
PORTB = wave[cnt_wave];
cnt_wave = (cnt_wave+1) & 0b00111111; //カウント(64バイトで1周期)
}
//*************************
//メイン関数
//*************************
int main(void){
/*ローカル変数宣言*/
uint8_t sw_state_old=0; //前回のスイッチの状態
/*入出力ポート設定*/
PORTA = 0b00000011;//プルアップ
PORTD = 0b01111111;
PORTB = 0;
DDRA = 0x00; //入力
DDRD = 0x00; //入力
DDRB = 0xff; //出力
DDRD |=(1<<PD6);
/*カウンタ1の設定*/
TCCR1A=0;
TCCR1B |= (1<<WGM12)|(1<<CS10);//CTC動作,分周なし
TCCR1C=0;
OCR1A=0x0fff; //比較一致TOP値(後で再設定)
TIMSK |= (1<<OCIE1A); //割り込み許可
getSW(&sw_state_old);
changeWave(sw_state_old);
sei(); //全割り込み許可
for(;;){
if(!cnt_wave){ //波形生成カウンタが0なら(1周期ごとに)
if( getSW(&sw_state_old) ){ //SW入力変化があれば
changeWave(sw_state_old); //波形変更
}
}
}
return 0;
}
//*************************
//スイッチの読み込み
//引数 前回のスイッチの状態(ポインタ)
//戻り値 0:スイッチ変更なし
// 1:スイッチ変更あり
//*************************
uint8_t getSW(uint8_t *old_sw){
uint8_t new_sw=(PIND<<2) | (PINA&0b00000011);
if(*old_sw!=new_sw){
*old_sw=new_sw;
return 1;
}
return 0;
}
//*************************
//波形変更
//引数 スイッチの状態
//*************************
void changeWave(uint8_t sw_state){
uint8_t frequency =0;
uint8_t waveform =0;
uint8_t i=0;
sw_state = ~sw_state;
frequency = reversalBits(sw_state)&0x0f;
waveform = sw_state & 0x0f;
if(frequency<=2){ //1Hz以下なら
TCCR1B = (TCCR1B & 0b11111000) | (1<<CS11); //8分周
}else{
TCCR1B = (TCCR1B & 0b11111000) | (1<<CS10); //分周無し
}
OCR1A=pgm_read_word(&data_freq[frequency]); //TOP値設定
switch(waveform){
case WAVEFORM_SIN:
for(i=0;i<17;i++)wave[i]=pgm_read_byte(&data_sin[i]);
for(i=1;i<17;i++)wave[16+i]=wave[16-i];
for(i=1;i<17;i++)wave[32+i]=256-wave[i];
for(i=0;i<15;i++)wave[49+i]=wave[47-i];
break;
case WAVEFORM_PULSE:
for(i=0;i<32;i++){
wave[i]=0xff;
wave[63-i]=0;
}
break;
case WAVEFORM_SAW:
for(i=0;i<64;i++)wave[i]=i*4;
break;
case WAVEFORM_SAW_R:
for(i=0;i<64;i++)wave[63-i]=i*4;
break;
}
}
//*************************
//ビット逆順
//*************************
uint8_t reversalBits(uint8_t bits){
bits=( bits << 4) | ( bits >> 4);
bits=((bits & 0x33) << 2) | ((bits & 0xcc) >> 2);
bits=((bits & 0x55) << 1) | ((bits & 0xaa) >> 1);
return bits;
}
|