/*
mode0:全オフ
mode1:セレクトしたHC595のO0とO7のオンオフ
mode2:セレクトしたHC595をすべてオンオフ
mode3:すべてのLEDのオンオフ
*/
//#define F_CPU 16000000UL
#define hc595_dat D,2
#define hc595_clk D,3
#define hc595_lat D,4
#define tm_dat B,4
#define tm_clk B,5
#define seg_wait 0.05
#define syodo 2 //照度0-7 7が一番明るい
// ******************************************
#define bis(addr,bit) (1&(addr>>bit))
#define bic(addr,bit) (!(1&(addr>>bit)))
#define cbi(addr,bit) addr &= ~(1<<bit)
#define sbi(addr,bit) addr |= (1<<bit)
#define _SET(type,name,bit) type ## name |= (1<<bit)
#define _CLEAR(type,name,bit) type ## name &= ~ (1<<bit)
#define _TGL(type,name,bit) type ## name ^= (1<<bit)
#define _GET(type,name,bit) ((type ## name >> bit) & 1)
#define _PUT(type,name,bit,value) type ## name = ( type ## name & ( ~ (1<<bit)) ) | ( ( 1 & (unsigned char)value ) << bit )
#define OUT(pin) _SET(DDR,pin)
#define IN(pin) _CLEAR(DDR,pin)
#define HIGH(pin) _SET(PORT,pin)
#define LOW(pin) _CLEAR(PORT,pin)
#define TGL(pin) _TGL(PORT,pin)
#define READ(pin) _GET(PIN,pin)
// *****************************************************
#include <avr/io.h>
#include <util/delay.h>
uint8_t relay[128];
uint8_t mode;
uint8_t pos;//HC595のセレクト位置0~15
uint8_t num_tm_data[] = { //dp無し
0b0111111,
0b0000110,
0b1011011,
0b1001111,
0b1100110,
0b1101101,
0b1111101,
0b0000111,
0b1111111,
0b1101111
};
void seg_start(void) {
_delay_us(seg_wait);
HIGH(tm_dat);
_delay_us(seg_wait);
HIGH(tm_clk);
_delay_us(seg_wait);
LOW(tm_dat);
}
void seg_send(uint8_t num) {
uint8_t i;
for (i = 0; i < 8; i++) {
_delay_us(seg_wait);
LOW(tm_clk);
if (bis(num, i))HIGH(tm_dat);
else LOW(tm_dat);
_delay_us(seg_wait);
HIGH(tm_clk);
}
_delay_us(seg_wait);
LOW(tm_clk);
_delay_us(seg_wait);
LOW(tm_dat);
_delay_us(seg_wait);
HIGH(tm_clk);
}
void seg_end(void) {
_delay_us(seg_wait);
LOW(tm_clk);
_delay_us(seg_wait);
LOW(tm_dat);
_delay_us(seg_wait);
HIGH(tm_clk);
_delay_us(seg_wait);
HIGH(tm_dat);
}
void disp(uint8_t rly) {//rlyが0は表示のみ。1なら表示とHC595操作
seg_start();
seg_send(0b01000000); //write increment コマンド1
seg_end();
seg_start();
seg_send(0xC0); //左の桁msb アドレス=コマンド2
seg_send(0);//左の2桁はmode
seg_send(num_tm_data[mode]);//左の2桁はmode
if (pos < 10) seg_send(0);//右2桁はHC595番号0~15
else seg_send(num_tm_data[1]);
seg_send(num_tm_data[pos % 10]);
seg_end();
seg_start();
seg_send(0b10001000 + syodo); //点灯 コマンド3=更新
seg_end();
if (rly == 0)return;
for (byte i = 0; i < 128; i++) { //リレー操作
if (relay[i])HIGH(hc595_dat);
else LOW(hc595_dat);
HIGH(hc595_clk);
LOW(hc595_clk);
}
HIGH(hc595_lat);
LOW(hc595_lat);
}
int main(void) {
OUT(hc595_dat);
OUT(hc595_clk);
OUT(hc595_lat);
OUT(tm_dat);
HIGH(tm_dat);
OUT(tm_clk);
PORTC = 0x3F; //PC0~5をプルアップ
uint16_t sw_state = 0xFFFF;
disp(0);
while (1) {
sw_state = sw_state << 8 | PINC;
if (sw_state & 0x100 && ~sw_state & 1) { //PC0
mode = (mode + 1) % 4; //mode+
pos = 0;
if (mode == 0) {
for (uint8_t i = 0; i < 128; i++)relay[i] = 0;
disp(1);
} else disp(0);
}
if (sw_state & 0x200 && ~sw_state & 2) { //PC1
mode = (mode + 3) % 4; //mode-
pos = 0;
if (mode == 0) {
for (uint8_t i = 0; i < 128; i++)relay[i] = 0;
disp(1);
} else disp(0);
}
if (sw_state & 0x400 && ~sw_state & 4) { //PC2
pos = (pos + 1) % 16; //HC595+
disp(0);
}
if (sw_state & 0x800 && ~sw_state & 8) { //PC3
pos = (pos + 15) % 16; //hc595-
disp(0);
}
if (sw_state & 0x1000 && ~sw_state & 0x10) { //PC4(ON)
if (mode == 1) {
relay[8 * pos] = 1;
relay[8 * pos + 7] = 1;
} else if (mode == 2) {
for (uint8_t i = 0; i < 8; i++)relay[pos + i] = 1;
} else if (mode == 3) {
for (uint8_t i = 0; i < 128; i++)relay[i] = 1;
}
disp(1);
}
if (sw_state & 0x1100 && ~sw_state & 0x11) { //PC5(OFF)
if (mode == 1) {
relay[8 * pos] = 0;
relay[8 * pos + 7] = 0;
} else if (mode == 2) {
for (uint8_t i = 0; i < 8; i++)relay[pos + i] = 0;
} else if (mode == 3) {
for (uint8_t i = 0; i < 128; i++)relay[i] = 0;
}
disp(1);
}
_delay_ms(5);
}
}
mode+
mode-
595+
595-
ON
OFF
MODE
595番号