ソースコード

#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--;

	
		}
}