atmega128+LDM+winavr 전광판 소스 입니다.
글자가 좌측으로 흘러갑니다.
다른 도트 매트릭스 소스와 다른 점이 있다면 뷰 영역과 데이터 영역을 분리했습니다.
말이 어려운데 별게 아니고 도트 매트릭스에 나타낼 내용은 ViewArea 라는 배열에, 나타내고 싶은 내용은 DataArea 라는 배열에 저장됩니다.
보통은 보여주는 내용 자체가 데이터 내용이죠.
이렇게 분리하면 유리한 것이 통신 등을 통해 메시지 내용을 변경하거나 다른 조작을 하는데 있어서 편합니다.
예를 들어 내용과 무관하게 테두리를 그리거나 특정 효과를 주거나 하는 경우죠.
그리고 타이머를 이용해서 스크롤이 되도록 했습니다.
제가 사용하는 LDM은 16*32 입니다.
enable 신호와 latch 신호는 모듈별로 다를수 있기 때문에 데이터 쉬트 타이밍 차트를 참고하세요.
아래 영상 첫부분에 스크롤 되다가 다시 시작하는 것은 윈도 무비 메이커로 만들다가 잘못 들어간 겁니다. ^^
char int8_t 1
unsigned char uint8_t 1
int int16_t 2
unsigned int uint16_t 2
long int32_t 4
unsigned long uint32_t 4
long long int64_t 8
unsigned long long uint64_t 8
intptr_1 2 int16_t와 같음
uintptr_t 2 uint16_t와 같음
float 4
double 8
*/
#include <avr/io.h>
#define F_CPU 16000000UL
//#include <util/delay.h>
#include <avr/interrupt.h>
uint16_t timer_flag = 0;
int8_t MessageIndex = 0;
#ifndef BV
#define BV(bit) (1<<(bit))
#endif
#ifndef cbi
#define cbi(reg,bit) reg &= ~(BV(bit))
#endif
#ifndef sbi
#define sbi(reg,bit) reg |= (BV(bit))
#endif
#define latch_high sbi(PORTB,0)
#define latch_low cbi(PORTB,0)
#define clock_high sbi(PORTB,1)
#define clock_low cbi(PORTB,1)
#define green_on sbi(PORTB,2)
#define green_off cbi(PORTB,2)
#define red_on sbi(PORTB,3)
#define red_off cbi(PORTB,3)
#define enable_high sbi(PORTB,4)
#define enable_low cbi(PORTB,4)
//int s = 0x3d0A; // 1초 만들기 위한 값
// A0~A3 : PORTD 0 ~ PORTD 3
int16_t DataAreaIndex, Column = 0;
int16_t MaxColumn = 320;
//unsigned int array[0][16] =
uint16_t ViewArea[2][16] = // 16*16*2 화면에 보여지는 영역
{
{ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 }, // 0
{ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 } // 1
};
uint16_t DataArea[20][16] = // 16*16*20(320) 데이터 영역
{
{ 0x0000,0x3F08,0x0088,0x0088,0x008E,0x0108,0x0608,0x7808,0x0008,0x0000,0x1FF8,0x1008,0x1008,0x1008,0x0FF0,0x0000 }, // 0
{ 0x0000,0x0408,0x0408,0x0408,0x0408,0x0408,0x040E,0x0A08,0x0A08,0x1108,0x1108,0x2088,0x4048,0x4048,0x0008,0x0000 }, // 1
{ 0x0000,0x0008,0x3FE8,0x0208,0x0208,0x0508,0x0888,0x1048,0x6228,0x0208,0x0208,0x0208,0x7FE8,0x0008,0x0008,0x0000 }, // 2
{ 0x0000,0x0080,0x0140,0x0630,0x380E,0x0080,0x0080,0x3FFE,0x0000,0x03E0,0x0C18,0x1004,0x1004,0x0C18,0x03E0,0x0000 }, //
{ 0x0000,0x07F0,0x0808,0x1004,0x1004,0x1004,0x1004,0x1004,0x1004,0x1004,0x1004,0x1004,0x7C04,0x3804,0x1004,0x0000 }, //
{ 0x0000,0x1F88,0x2008,0x2008,0x3EF8,0x2008,0x2008,0x2008,0x1FC8,0x0008,0x0008,0x1000,0x1000,0x1000,0x0FF8,0x0000 }, //
{ 0x0000,0x1000,0x3000,0x7FF8,0x3004,0x1004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0000 }, //
{ 0x0000,0x1000,0x3000,0x7FF8,0x3004,0x1004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,0x0000 }, //
{ 0x0000,0x0008,0x000C,0x1FFE,0x200C,0x2008,0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,0x0000 }, //
{ 0x0000,0x0008,0x000C,0x1FFE,0x200C,0x2008,0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,0x2000,0x0000 }, //
{ 0x0000,0x0008,0x2088,0x2088,0x2088,0x2088,0x3F88,0x2088,0x2088,0x2088,0x2088,0x2088,0x1F08,0x0008,0x0008,0x0000 }, //
{ 0x0000,0x0408,0x0408,0x0408,0x0A0E,0x1108,0x2088,0x4048,0x0008,0x03C0,0x0C30,0x1008,0x1008,0x0C30,0x03C0,0x0000 }, //
{ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 }, // 18
{ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 }, // 19
{ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 }, // 18
{ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 } // 19
};
/* time delay for us */
void DelayUs(unsigned char time_us)
{
register unsigned char i;
for(i = 0; i < time_us; i++) // 4 cycle +
{
asm volatile(" PUSH R0 "); // 2 cycle +
asm volatile(" POP R0 "); // 2 cycle +
asm volatile(" PUSH R0 "); // 2 cycle +
asm volatile(" POP R0 "); // 2 cycle +
asm volatile(" PUSH R0 "); // 2 cycle +
asm volatile(" POP R0 "); // 2 cycle = 16 cycle = 1 us for 16MHz
}
}
/* time delay for ms */
void DelayMs(unsigned int time_ms)
{
register unsigned int i;
for(i = 0; i < time_ms; i++)
{
DelayUs(250);
DelayUs(250);
DelayUs(250);
DelayUs(250);
}
}
/* time delay for s */
void DelayS(unsigned int time_s)
{
register unsigned int i;
for(i = 0; i < time_s; i++)
{
DelayMs(250);
DelayMs(250);
DelayMs(250);
DelayMs(250);
}
}
void LDM_ChangeRow(int Row)
{
latch_low; // 래치 출력 , 한행 display 완료.
enable_high;
clock_low;
PORTD = Row;
clock_high;
enable_low;
}
//void LDM_print(unsigned int temp_data[9][16], int mat, int color)
void LDM_print(void)
{
unsigned int ROW = 0;
uint32_t font;
int COL;
red_off;
green_off;
// PORTD = 0;
//ViewArea[0][0] = Column;
//ViewArea[0][1] = DataAreaIndex;
// ViewArea[0][0] = PORTC;
for (ROW = 0; ROW < 16; ROW++)
{
font = ViewArea[0][ROW];
for (COL = 0; COL < 16; COL ++)
{
if (font & 0x8000)
{
green_on;
}
else
{
green_off;
}
font = font << 1; // 다음 도트의 데이터를 검출하기 위해 한 비트 shift
clock_high;
clock_low;
}
font = ViewArea[1][ROW];
for (COL = 0; COL < 16; COL ++)
{
if (font & 0x8000)
{
green_on;
}
else
{
green_off;
}
font = font << 1; // 다음 도트의 데이터를 검출하기 위해 한 비트 shift
clock_high;
clock_low;
}
enable_high;
latch_high;
latch_low;
enable_low;
PORTD = ROW;
}
}
void ChangeDotMatrixArray(void)
{
int Row;
/*
switch(MessageIndex)
{
case 0:
for (Row=0;Row<16;Row++)
{
DotMatrix[Row]=Default[Row];
}
break;
case 1:
for (Row=0;Row<16;Row++)
{
DotMatrix[Row]=ThankYou[Row];
}
break;
case 2:
for (Row=0;Row<16;Row++)
{
DotMatrix[Row]=Sorry[Row];
}
break;
case 3:
for (Row=0;Row<16;Row++)
{
DotMatrix[Row]=UTurn[Row];
}
break;
case 4:
for (Row=0;Row<16;Row++)
{
DotMatrix[Row]=LeftTurn[Row];
}
break;
case 5:
for (Row=0;Row<16;Row++)
{
DotMatrix[Row]=RightTurn[Row];
}
break;
case 6:
for (Row=0;Row<16;Row++)
{
DotMatrix[Row]=Emergency[Row];
}
break;
}
timer_flag = 0;
*/
}
ISR(TIMER0_OVF_vect)
{
unsigned int ROW = 0;
//16.384msec 주기
timer_flag++;
if(timer_flag > 3) //16.384msec * 61 = 1초
{
timer_flag=0;
// -------------------------------------------------------------------------
DataAreaIndex = Column / 16;
if (DataAreaIndex > 21)
{
DataAreaIndex = 0;
}
for (ROW = 0; ROW < 16; ROW++)
{
ViewArea[0][ROW] = ViewArea[0][ROW] << 1;
if (ViewArea[1][ROW] & 0x8000)
{
ViewArea[0][ROW] = ViewArea[0][ROW] | 0x0001;
}
ViewArea[1][ROW] = ViewArea[1][ROW] << 1;
if (DataArea[DataAreaIndex][ROW] << (Column % 16) & 0x8000)
{
ViewArea[1][ROW] = ViewArea[1][ROW] | 0x0001;
}
}
Column ++;
if (Column > MaxColumn)
{
Column = 0;
}
// -------------------------------------------------------------------------
}
}
int main(void)
{
unsigned int ROW, temp=0;
int scroll, color=0;
DelayS(1);
DDRB = 0xFF; // B 포트 출력
PORTB = 0x00; // B 포트 출력 OFF
DDRD = 0xFF; // D 포트 출력
PORTD = 0x00; // D 포트 출력 OFF
TCCR0 = 0x07;
TIMSK = 0x01; // 16 MHz/1024/256 = 16.384msec
SREG |= 0x80; //전체 인터럽트 이네이블.
DDRC = 0x00;
PORTC = 0x01;
DataAreaIndex = 0;
Column = 0;
while(1)
{
LDM_print();
}
}