#include "src/io_Header.h"
const int __attribute__((progmem)) string[][16] = { 
  0x00, 0x00, 0x1800, 0x18fc, 0x1980, 0x1980, 0x1980, 0x7980, 0x18c0, 0x18c0, 0x1860, 0x1830, 0x181c, 0x1800, 0x00, 0x00, //가
};
#define string_moving_speed_value 50
unsigned char FontColor = 0; // 문자 색상 설정 변수
unsigned char sequence = 0;  // 도트매트릭스의 디스플레이 모션 방식 설정
unsigned int Decrease_cnt = 16; // 도트매트릭스 왼쪽, 오른쪽 시프트 변수
unsigned int Increase_cnt = 0; // 도트매트릭스 왼쪽, 오른쪽 시프트 변수2 
unsigned int str_speed_cnt = 0;
ISR(TIMER2_OVF_vect)  // 타이머/카운터 인터럽트 서비스 루틴, Tick time per 1mS!
{
  static unsigned int cnt = 0;
  str_speed_cnt++;
  if (str_speed_cnt > string_moving_speed_value)  // 문자가 50mS 머문 후 시프트 시작
  {
    str_speed_cnt = 0; // 문자 이동 속도 카운터 초기화
    Decrease_cnt--; //좌측 시프트 카운터 변수
    Increase_cnt++; // 우측 시프트 카운트 변수 
    if (Decrease_cnt == 0 || Increase_cnt == 16) // 좌측 or 우측 시프트 카운트 변수가 16번 동작했을 때?
    {
      Decrease_cnt = 16;
      Increase_cnt = 0;
      sequence++; //16번의 동작이 완료되었을때 다음 시퀸스로 이동하기 위한 카운터 변수 
      if (sequence > 2) // 시퀸스가 모두 종료되면
      {
        sequence = 0; // 시퀸스 초기화 해 무한 반복  
      }
    }
  }
  TCNT2 |= 0x06;
}
void setup()
{
  //입출력 레지스터 설정 초기화
  DDRB = 0x3f;  // PORTB 5~0 핀 출력으로 설정
  DDRC = 0x08;  // PORTC 3 핀 출력으로 설정
  DDRD = 0xfc;  // PORTD 7~2 핀 출력으로 설정
  //Timer/Conunter Interrupt initialization
  TCCR2A = 0x00;
  TCCR2B = 0x04;  // 타이머 카운터2 노멀 모드, 64분주 
  TIMSK2 = 0x01;  // 타이머 카운터2 인터럽트 허용
  TCNT2 = 0x06; // 타이머 카운터2 초기값: 6
  SREG = 0x80;  // 인터럽트 허용
}
void loop()
{
  static unsigned int i_cnt = 0;  //for문을 위한 사용자 변수
  unsigned int Buff1[16] = { 0 };
  // 16x16 도트매트릭스1 문자 사용자 배열
  unsigned int Buff2[16] = { 0 };
  // 16x16 도트매트릭스2 출력 사용자 배열
  unsigned char High, Low, High2, Low2 = 0;
  // 마스킹을 위한 상위 및 하위 바이트 사용자 변수
  FontColor = Red;
  for (i_cnt = 0; i_cnt < 16; i_cnt++)  // 출력할 문자 복사하기 위한 for문
  {
    switch(sequence)
    {
      case 0: 
        Buff1[i_cnt] = 0;
        // 1열부터 16열까지의 16x16 도트매트릭스1 데이터 복사
        Buff2[i_cnt] = pgm_read_word(&string[0][i_cnt]) << Decrease_cnt; break;
        // 17열부터 32열까지의 16x16 도트매트릭스2 데이터 복사
      case 1: 
        Buff1[i_cnt] = pgm_read_word(&string[0][i_cnt]) << Decrease_cnt;
        // 1열부터 16열까지의 16x16 도트매트릭스2 데이터 복사
        Buff2[i_cnt] = pgm_read_word(&string[0][i_cnt]) >> Increase_cnt; break;
        // 17열부터 32열까지의 16x16 도트매트릭스1 데이터 복사
      case 2: 
        Buff1[i_cnt] = pgm_read_word(&string[0][i_cnt]) >> Increase_cnt;
        // 1열부터 16열까지의 16x16 도트매트릭스2 데이터 복사
        Buff2[i_cnt] = 0; break;
        // 17열부터 32열까지의 16x16 도트매트릭스2 데이터 복사
    }
  }
  for (i_cnt = 0; i_cnt < 16; i_cnt++)
  {
    High = (Buff1[i_cnt] >> 8);  //16x16 도트매트릭스1 상위 바이트 저장
    Low = (Buff1[i_cnt] &0xff);  //16x16 도트매트릭스1 하위 바이트 저장
    High2 = (Buff2[i_cnt] >> 8);  //16x16 도트매트릭스2 상위 바이트 저장
    Low2 = (Buff2[i_cnt] &0xff);  //16x16 도트매트릭스2 하위 바이트 저장
    row_dynamic(i_cnt);
    // 행(Row) 선택하기 row_dynamic 함수 호출, 인자값 i_cnt값이 전달 됨
    Shift_Register(High, Low, i_cnt, FontColor);
    // 저장된 16x16 도트매트릭스1 데이터 전송
    Shift_Register(High2, Low2, i_cnt, FontColor);
    // 저장된 16x16 도트매트릭스2 데이터 전송
    ActivePulse();
    // 데이터 전송 후 래치신호를 전송하는 ActivePulse함수 호출
  }
}
