#include <avr/io.h>
#define sbi(PORT,BIT) PORT|=_BV(BIT)
#define cbi(PORT,BIT) PORT&=~_BV(BIT)
#define ibi(sfr, bit) (bit_is_set(sfr,bit)?1:0)
#define c_set 8 //カラーセット
void push();
void colorset();
void ledset(uint8_t, uint8_t, uint8_t);
void encode(char);
void flash(uint8_t, uint8_t, uint8_t);
uint8_t red, blue, green;
unsigned char flag = 0, color = 0;
unsigned char takuto;
char bit0=0, bit1=0, odata=0, ndata=0, deff=0;
char stet;
char right = 0, left = 0;
//ロータリエンコーダ入力制御
//ロータリエンコーダ入力はグレイコードであることに注目し、
//それをバイナリコードにまず変換します。
//あとは波形の変化で右左を判定。
//詳しくは検索して(お
char getencorder(){
odata = ndata;
bit0 = ibi(PIND, 3);
bit1 = ibi(PIND, 4);
//ここから
bit0 = bit0 ^ bit1;
if(bit0 ==0 && bit1 == 0)
ndata = 0;
if(bit0 == 1 && bit1 == 0)
ndata = 1;
if(bit0 == 0 && bit1 == 1)
ndata = 2;
if(bit0 == 1 && bit1 == 1)
ndata = 3;
//ここまで変換
deff = ndata - odata;
if(deff == 1 || deff == -3){
return 1; //右に回した
}
else if(deff == -1 || deff == 3){
return 2; //左に回した
}
else
return 0; //エラー
}
int main(void) {
//プルアップに設定
DDRB = 0xff;
DDRD = 0x00;
PORTD = 0xff;
PORTB = 0xff;
colorset();
while(1) {
stet = getencorder();
if(bit_is_clear(PIND, 2)){
color = 0; //カラーリセット
push();
}
if(stet == 1 || stet == 2){
encode(stet);
}
flash(red, green, blue);
}
}
//プッシュスイッチ制御
//初期状態はflag=0
//赤セット後1
//青セット後2
//緑セット語3
void push(){
//チャタリングを防ぐため待機時間を入れるとよい。
while(1){
takuto = ibi(PIND, 2);
if(takuto == 1)
break;
}
if(flag == 0){
red = 0x0f;
ledset(red, 0x00, 0x00);
wait(2);
while(1){
takuto = ibi(PIND, 2);
if(takuto == 1)
break;
}
}
if(flag == 1){
green = 0x0f;
ledset(0x00, green, 0x00);
wait(2);
while(1){
takuto = ibi(PIND, 2);
if(takuto == 1)
break;
}
}
if(flag == 2){
blue = 0x0f;
ledset(0x00, 0x00, blue);
wait(2);
while(1){
takuto = ibi(PIND, 2);
if(takuto == 1)
break;
}
}
if(flag == 3){
flag = 0;
wait(2);
while(1){
takuto = ibi(PIND, 2);
if(takuto == 1)
break;
}
return;
}
}
//デフォルトで設定している色
//RGBで指定(色合いの正しさは保障できない)
void colorset(){
switch(color){
case 0: //white
red = 0xff;
green = 0xff;
blue = 0xff;
break;
case 1: //red
red = 0xff;
green = 0x00;
blue = 0x00;
break;
case 2: //green
red = 0x00;
green = 0xff;
blue = 0x00;
break;
case 3: //blue
red = 0x00;
green = 0x00;
blue = 0xff;
break;
case 4: //yellow
red = 0xff;
green = 0xff;
blue = 0x00;
break;
case 5: //sky blue
red = 0x00;
green = 0xff;
blue = 0xff;
break;
case 6: //purple
red = 0xff;
green =0x00;
blue = 0xff;
break;
case 7: //pink
red = 255;
green = 100;
blue = 100;
break;
case 8: //orange
red = 255;
green = 130;
blue = 0;
break;
default:
break;
}
}
//手動色セット制御関数
void ledset(uint8_t tr, uint8_t tg, uint8_t tb){
flag++;
while(1){
takuto = ibi(PIND, 2);
if(takuto == 1)
break;
}
while(1){
takuto = ibi(PIND, 2);
stet = getencorder();
if(takuto == 0)
return;
if(stet == 1 || stet == 2)
encode(stet);
switch(flag){
case 1:
flash(red, tg, tb);
break;
case 2:
flash(tr, green, tb);
break;
case 3:
flash(tr, tg, blue);
break;
default:
break;
}
}
}
//実際に手動で色合いを変更させる関数
void encode(char vector){
if(vector == 1){ //右回り
right++;
right %= 4; //右は感度がいいので4で割る
if(right != 0)
return;
if(flag == 1 && red < 0xea)
red += 20;
else if(flag == 1)
red = 0xff;
if(flag == 2 && green< 0xea)
green += 20;
else if(flag == 2)
green = 0xff;
if(flag == 3 && blue < 0xea)
blue += 20;
else if(flag == 3)
blue = 0xff;
if(flag == 0){
color++;
color %= (c_set +1) ;
colorset();
}
return;
}
if(vector == 2){ //左回り
left++;
left %= 2; //左の方が回しづらいので2で割る
if(left != 0)
return;
if(flag == 1 && red > 0x0f)
red -= 15;
else if(flag == 1 && red != 0x00)
red--;
if(flag == 2 && green > 0x0f)
green -= 15;
else if(flag == 2 && green != 0)
green--;
if(flag == 3 && blue > 0x0f)
blue -= 15;
else if(flag == 3 && blue != 0)
blue--;
if(flag == 0){
if(color != 0)
color--;
else
color = c_set;
colorset();
}
return;
}
return;
}
//LED点灯関数
void flash(uint8_t tr,uint8_t tg, uint8_t tb){
uint8_t cnt = 0xff;
PORTB = 0x00; //アノードコモンは0で点灯
while(cnt != 0){//0xffが入ると常にON
if(tr == 0x00)
sbi(PORTB, 0);
tr--;
if(tg == 0x00)
sbi(PORTB, 1);
tg--;
if(tb == 0x00)
sbi(PORTB, 2);
tb--;
cnt--;
}
}