#include "hal.h"
#include <string.h>
#define row_port PORT_A
#define col_port PORT_B
#define DIN A_0
#define CLK A_1
#define CS A_2
#define HW_DELAY() for(volatile uint8_t d=0; d<2; d++)
struct Matrixchar {
uint8_t name;
uint8_t data[8];
};
typedef enum {
left,
right,
up,
down,
} scroll_type;
volatile uint8_t data_buffer[32] = {0};
volatile uint8_t static_buffer[32] = {0};
const struct Matrixchar capital_letters[] = {
{' ', {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
{'A', {0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x00}},
{'B', {0x00, 0x7f, 0x49, 0x49, 0x49, 0x49, 0x36, 0x00}},
{'C', {0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x00}},
{'D', {0x00, 0x7f, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x00}},
{'E', {0x7e, 0x02, 0x02, 0x7e, 0x02, 0x02, 0x7e, 0x00}},
{'L', {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00}},
{'T', {0x7e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00}},
{'S', {0x00, 0x46, 0x49, 0x49, 0x49, 0x49, 0x49, 0x31}},
{'W', {0x42, 0x42,0x42,0x42,0x5a, 0x66, 0x42, 0x00}},
{'1', {0x00, 0x00, 0x42, 0x41, 0x7f, 0x40, 0x40, 0x00}},
{'2', {0x00, 0x79, 0x49, 0x49, 0x49, 0x49, 0x49, 0x4f}},
};
const struct Matrixchar small_letters[] = {
{'e', {0x00, 0x00, 0x3c, 0x42, 0x7e, 0x04, 0x38, 0x00}},
{'l', {0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00}},
{'c', {0x00, 0x00, 0x3c, 0x02, 0x02, 0x42, 0x3c, 0x00}},
{'o', {0x00,0x00, 0x3c, 0x42, 0x42, 0x42, 0x3c, 0x00}},
{'m', {0x00, 0x00, 0x2a, 0x54,0x54,0x54,0x54, 0x00}},
{'S', {0x00, 0x46, 0x49, 0x49, 0x49, 0x49, 0x49, 0x31}},
};
const uint8_t Cap_A[8] = {0x18, 0x24, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x00};
const uint8_t Cap_S[8] = {0xfc, 0x02, 0x02, 0x7c, 0x80, 0x80, 0x7e, 0x00};
const uint8_t Cap_B[8] = {0x3e, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x3e, 0x00};
const uint8_t Cap_T[8] = {0x7e, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00};
const uint8_t Cap_E[8] = {0x7e, 0x02, 0x02, 0x7e, 0x02, 0x02, 0x7e, 0x00};
const uint8_t Cap_L[8] = {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00};
const uint8_t Cap_A_1[8] = {0x00, 0x00, 0x18, 0x34, 0x54, 0x54, 0x54, 0x18};
//numbers
const uint8_t num_1[8] = {0x18, 0x14, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00};
const uint8_t num_2[8] = {0x00, 0x79, 0x49, 0x49, 0x49, 0x49, 0x49, 0x4f};
//small letters
const uint8_t small_a[8] = {0x00, 0x00, 0x31, 0x49, 0x49, 0x49, 0x36, 0x40};
const uint8_t small_q[8] = {0x00, 0x06, 0x09, 0x09, 0x09, 0x76, 0x80, 0x40};
//symbols
const uint8_t symbol_dollar[8] = {0x00, 0x46, 0x49, 0x49, 0xff, 0xff, 0x49, 0x31};
const uint8_t symbol_hash[8] = {0x00, 0xa8, 0xa8, 0x78, 0x2c, 0x3a, 0x2c, 0x2a};
const uint8_t symbol_alpha[8] = {0x18, 0x24, 0x24, 0x18, 0x1c, 0x22, 0x41, 0x00};
const uint8_t symbol_ohm[8] = {0x80, 0xb8, 0xc4, 0x04, 0x04, 0xc4, 0xb8, 0x80};
const uint8_t Space_void[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
void setup() {
max7219_init();
/*load_static_buffer(Cap_E,Cap_T,Cap_A,Cap_L);
entry_from_above(3);
//for(volatile long i=0;i<10*450000;i++);
leave_from_below();*/
uint8_t scroll_time=3;
str_entry_from_above("Welcome",&scroll_time);
/*while(1)
{ str_entry_from_left("ETAL");
str_leave_by_right();}*/
}
void loop() {
// put your main code here, to run repeatedly:
}
void cs_active()
{
pin_drive_out(CS, 0);
}
void cs_idle()
{
pin_drive_out(CS, 1);
}
void clk_low()
{
pin_drive_out(CLK, 0);
}
void clk_high()
{
pin_drive_out(CLK, 1);
}
void write_byte(volatile uint8_t u_byte)
{
for (uint8_t i = 0; i < 8; i++)
{
clk_low();
(u_byte & 0x80) ? (pin_drive_out(DIN, 1)) : (pin_drive_out(DIN, 0));
HW_DELAY();
u_byte <<= 1;
clk_high();
HW_DELAY();
}
}
void send(uint8_t matrix_addr, uint8_t matrix_data)
{
cs_active();
for(uint8_t i=0;i<4;i++)
{
write_byte(matrix_addr);
write_byte(matrix_data);
}
cs_idle();
}
void max7219_init() {
init_pin(CLK, output);
init_pin(DIN, output);
init_pin(CS, output);
cs_idle();
send(0x09, 0x00); // Decode Mode: No decode (Matrix mode)
send(0x0A, 0x03); // Intensity: 3/15 brightness
send(0x0B, 0x07); // Scan Limit: Display all 8 rows (0-7)
send(0x0C, 0x01); // Shutdown: 0x01 = Normal Operation
send(0x0F, 0x00); // Display Test: 0x00 = Off
// Clear the matrix initially
for (uint8_t i = 1; i <= 8; i++) {
send(i, 0x00);
}
}
/*void two_letter_display(volatile uint8_t first_letter_arr[8], volatile uint8_t second_letter_arr[8], volatile uint8_t third_letter_arr[8], volatile uint8_t fourth_letter_arr[8])
{
for (uint8_t i = 1; i < 9; i++)
send(i, first_letter_arr[i - 1], i, second_letter_arr[i - 1], i, third_letter_arr[i - 1], i, fourth_letter_arr[i - 1]);
}*/
void load_static_buffer(volatile uint8_t first_letter_arr[8], volatile uint8_t second_letter_arr[8], volatile uint8_t third_letter_arr[8], volatile uint8_t fourth_letter_arr[8])
{
for (uint8_t i = 0; i < 8; i++)
{
static_buffer[i] = first_letter_arr[i];
static_buffer[8 + i] = second_letter_arr[i];
static_buffer[16 + i] = third_letter_arr[i];
static_buffer[24 + i] = fourth_letter_arr[i];
}
}
void refresh_display()
{
for (uint8_t row = 1; row < 9; row++)
{
cs_active();
for (uint8_t m = 0; m < 4; m++)
{
write_byte(row);
write_byte(data_buffer[(m * 8) + (row - 1)]);
}
cs_idle();
}
}
uint8_t* fetch_char_data(uint8_t c)
{
for (uint8_t i = 0; i < 13; i++)
{
if (capital_letters[i].name == c)
return capital_letters[i].data;
if (small_letters[i].name == c)
return small_letters[i].data;
}
}
void str_entry_from_right(volatile uint8_t *str)
{
for (int8_t m = 0; m < strlen((uint8_t*)str); m++)
{
uint8_t *cur_char_arr[8] = {0};
for (uint8_t out = 0; out < 8; out++)
{
uint8_t *cur_char_arr = fetch_char_data(str[m]);
for (uint8_t inn = 0; inn < 8; inn++)
{
uint8_t carry43 = data_buffer[24 + inn] & 0x01;//get LSB of matrix 4
uint8_t carry32 = data_buffer[16 + inn] & 0x01;//get LSB of matrix 3
uint8_t carry21 = data_buffer[8 + inn] & 0x01;//get LSB of matrix 2
data_buffer[24 + inn] >>= 1;//right shift
data_buffer[24 + inn] |= cur_char_arr[inn] & (1 << out) ? 0x80 : 0x00;//get one by one led status of right most column in matrix 4
data_buffer[16 + inn] >>= 1;//shift right
data_buffer[16 + inn] |= carry43 ? 0x80 : 0x00;//get one by one led status of right most column in matrix 3
data_buffer[8 + inn] >>= 1;//shift right
data_buffer[8 + inn] |= carry32 ? 0x80 : 0x00;//get one by one led status of right most column in matrix 2
data_buffer[inn] >>= 1;//shift right
data_buffer[inn] |= carry21 ? 0x80 : 0x00;//get one by one led status of right most column in matrix 1
}
for (volatile unsigned long i = 0; i < 100000; i++);//each slice or column enters slowly
refresh_display();
}
}
}
void str_leave_by_left(uint8_t time)
{
for (int8_t m = 0; m < 4; m++)
{
uint8_t *cur_char_arr[8] = {0};
for (uint8_t out = 0; out < 8; out++)
{
for (uint8_t inn = 0; inn < 8; inn++)
{
uint8_t carry43 = data_buffer[24 + inn] & 0x01;//get LSB of matrix 4
uint8_t carry32 = data_buffer[16 + inn] & 0x01;//get LSB of matrix 3
uint8_t carry21 = data_buffer[8 + inn] & 0x01;//get LSB of matrix 2
data_buffer[24 + inn] >>= 1;//right shift
data_buffer[24 + inn] |= 0x00;//get one by one led status of right most column in matrix 4
data_buffer[16 + inn] >>= 1;//shift right
data_buffer[16 + inn] |= carry43 ? 0x80 : 0x00;//get one by one led status of right most column in matrix 3
data_buffer[8 + inn] >>= 1;//shift right
data_buffer[8 + inn] |= carry32 ? 0x80 : 0x00;//get one by one led status of right most column in matrix 2
data_buffer[inn] >>= 1;//shift right
data_buffer[inn] |= carry21 ? 0x80 : 0x00;//get one by one led status of right most column in matrix 1
}
for (volatile unsigned long i = 0; i < (405000/32)*time; i++);//each slice or column enters slowly
refresh_display();
}
}
}
void str_entry_from_left(volatile uint8_t *str)
{
for (int8_t m = strlen((uint8_t*)str)-1; m >=0 ; m--)
{
uint8_t *cur_char_arr[8] = {0};
for (int8_t out = 7; out >= 0; out--)
{
uint8_t *cur_char_arr = fetch_char_data(str[m]);
for (uint8_t inn = 0; inn < 8; inn++)
{
uint8_t carry34 = data_buffer[16 + inn] & 0x80;//get MSB of matrix 3
uint8_t carry23 = data_buffer[8 + inn] & 0x80;//get MSB of matrix 2
uint8_t carry12 = data_buffer[inn] & 0x80;//get MSB of matrix 1
data_buffer[24 + inn] <<= 1;//right shift
data_buffer[24 + inn] |= carry34 ?0x01 : 0x00;//get one by one led status of LEFT most column in matrix 4
data_buffer[16 + inn] <<= 1;//shift right
data_buffer[16 + inn] |= carry23 ?0x01 : 0x00;//get one by one led status of LEFT most column in matrix 3
data_buffer[8 + inn] <<= 1;//shift right
data_buffer[8 + inn] |= carry12 ? 0x01 : 0x00;//get one by one led status of LEFT most column in matrix 2
data_buffer[inn] <<= 1;//shift right
data_buffer[inn] |= cur_char_arr[inn] & (1 << out) ? 0x01 : 0x00;//get one by one led status of LEFT most column in matrix 1
}
for (volatile unsigned long i = 0; i < 100000; i++);//each slice or column enters slowly
refresh_display();
}
}
}
void str_leave_by_right(void)
{
for (int8_t m = 0; m < 4; m++)
{
uint8_t *cur_char_arr[8] = {0};
for (uint8_t out = 0; out < 8; out++)
{
for (uint8_t inn = 0; inn < 8; inn++)
{
uint8_t carry34 = data_buffer[16 + inn] & 0x80;//get LSB of matrix 4
uint8_t carry23 = data_buffer[8 + inn] & 0x80;//get LSB of matrix 3
uint8_t carry12 = data_buffer[inn] & 0x80;//get LSB of matrix 2
data_buffer[24 + inn] <<= 1;//right shift
data_buffer[24 + inn] |= carry34 ?0x01 : 0x00;//get one by one led status of right most column in matrix 4
data_buffer[16 + inn] <<= 1;//shift right
data_buffer[16 + inn] |= carry23 ?0x01 : 0x00;//get one by one led status of right most column in matrix 3
data_buffer[8 + inn] <<= 1;//shift right
data_buffer[8 + inn] |= carry12 ? 0x01 : 0x00;//get one by one led status of right most column in matrix 2
data_buffer[inn] <<= 1;//shift right
data_buffer[inn] |= 0x00;//get one by one led status of right most column in matrix 1
}
for (volatile unsigned long i = 0; i < 100000; i++);//each slice or column enters slowly
refresh_display();
}
}
}
void entry_from_below(uint8_t time)
{
for(uint8_t out=0;out<8;out++)
{
for(int8_t inn=0;inn<7;inn++)
{
data_buffer[inn]=data_buffer[inn+1];
data_buffer[16+inn]=data_buffer[16+inn+1];
data_buffer[24+inn]=data_buffer[24+inn+1];
data_buffer[8+inn]=data_buffer[8+inn+1];
}
data_buffer[7]=static_buffer[out];
data_buffer[15]=static_buffer[8+out];
data_buffer[23]=static_buffer[16+out];
data_buffer[31]=static_buffer[24+out];
for (volatile unsigned long i = 0; i < (405000/8)*time; i++);
refresh_display();
}
}
void leave_from_above()
{
for(uint8_t out=0;out<8;out++)
{
for(int8_t inn=0;inn<7;inn++)
{
data_buffer[inn]=data_buffer[inn+1];
data_buffer[8+inn]=data_buffer[8+inn+1];
data_buffer[16+inn]=data_buffer[16+inn+1];
data_buffer[24+inn]=data_buffer[24+inn+1];
}
data_buffer[7]=0x00;
data_buffer[15]=0x00;
data_buffer[23]=0x00;
data_buffer[31]=0x00;
for (volatile unsigned long i = 0; i < 400000; i++);
refresh_display();
}
}
void entry_from_above(uint8_t time)
{
for(uint8_t out=0; out<8; out++)
{
for(int8_t inn=7; inn > 0; inn--)
{
data_buffer[inn] = data_buffer[inn-1];
data_buffer[8+inn] = data_buffer[8+inn-1];
data_buffer[16+inn] = data_buffer[16+inn-1];
data_buffer[24+inn] = data_buffer[24+inn-1];
}
data_buffer[0] = static_buffer[7-out];
data_buffer[8] = static_buffer[15-out];
data_buffer[16] = static_buffer[23-out];
data_buffer[24] = static_buffer[31-out];
for (volatile unsigned long i = 0; i < (405000/8)*time; i++);
refresh_display();
}
}
void leave_from_below()
{
for(uint8_t out=0;out<8;out++)
{
for(int8_t inn=7;inn>0;inn--)
{
data_buffer[inn]=data_buffer[inn-1];
data_buffer[8+inn]=data_buffer[8+inn-1];
data_buffer[16+inn]=data_buffer[16+inn-1];
data_buffer[24+inn]=data_buffer[24+inn-1];
}
data_buffer[0]=0x00;
data_buffer[8]=0x00;
data_buffer[16]=0x00;
data_buffer[24]=0x00;
for (volatile unsigned long i = 0; i < 400000; i++);
refresh_display();
}
}
void str_entry_from_below(uint8_t *str,uint8_t *time)
{
uint8_t str_len=strlen(str);
for(int8_t index=0;index<str_len;index=index+4)
{
uint8_t *char1=fetch_char_data(str[index]);
uint8_t *char2=(index+1)<str_len?fetch_char_data(str[index+1]):fetch_char_data(' ');
uint8_t *char3=(index+2)<str_len?fetch_char_data(str[index+2]):fetch_char_data(' ');
uint8_t *char4=(index+3)<str_len?fetch_char_data(str[index+3]):fetch_char_data(' ');
for(uint8_t out=0;out<8;out++)//character bringing in loop
{
for(int8_t inn=0;inn<7;inn++)//shifting loop
{
data_buffer[inn]=data_buffer[inn+1];
data_buffer[16+inn]=data_buffer[16+inn+1];
data_buffer[24+inn]=data_buffer[24+inn+1];
data_buffer[8+inn]=data_buffer[8+inn+1];
}
data_buffer[7]=char1[out];
data_buffer[15]=char2[out];
data_buffer[23]=char3[out];
data_buffer[31]=char4[out];
refresh_display();
for (volatile unsigned long i = 0; i < (405000/8)*(*time); i++);
}
}
}
void str_entry_from_above(uint8_t *str,uint8_t *time)
{
uint8_t str_len=strlen(str);
uint32_t timer_offset=(450000/8)/(2);
for(int8_t index=0;index<str_len;index=index+4)
{
uint8_t *char1=fetch_char_data(str[index]);
uint8_t *char2=(index+1)<str_len?fetch_char_data(str[index+1]):fetch_char_data(' ');
uint8_t *char3=(index+2)<str_len?fetch_char_data(str[index+2]):fetch_char_data(' ');
uint8_t *char4=(index+3)<str_len?fetch_char_data(str[index+3]):fetch_char_data(' ');
for(uint8_t out=0;out<8;out++)//character bringing in loop
{
for(int8_t inn=7;inn>0;inn--)//shifting loop
{
data_buffer[inn]=data_buffer[inn-1];
data_buffer[16+inn]=data_buffer[16+inn-1];
data_buffer[24+inn]=data_buffer[24+inn-1];
data_buffer[8+inn]=data_buffer[8+inn-1];
}
data_buffer[0]=char1[7-out];
data_buffer[8]=char2[7-out];
data_buffer[16]=char3[7-out];
data_buffer[24]=char4[7-out];
refresh_display();
for (volatile unsigned long i = 0; i < timer_offset*(*time); i++);
}
}
}