📄 hyperbar.c
字号:
// Firmware of HyperBar - USB Super Resource Monitor
//
// Compiler: ICCAVR 6.31A Pro
// Target: M8
// Crystal: 4.0000Mhz
// Description:
// Receives data packet from the AVR309 USB chip (AT90S2313),
// and converts the data into a form fitting for display.
// This program employs a popular mechanism called scanning
// to simultaneously light up the SMD LED array. Further more,
// a flash of the status LED indicates a successful reception
// of a data packet from the built-in UART.
#include <iom8v.h>
#include <macros.h>
#define SCALER 500
#define DA_SCALER 50
#define UD_SCALER 10
#define RX_BUF_SIZE 5
#define SOP_CHAR 0xBB
#define EOP_CHAR 0xEE
typedef unsigned char byte;
int da_counter;
byte rx_counter;
byte rx_buffer[RX_BUF_SIZE];
byte dataActive;
int ud_counter;
byte bar1_value, bar1_sample;
byte bar2_value, bar2_sample;
byte dots_sample;
void update_samples()
{
bar1_sample = rx_buffer[1];
bar2_sample = rx_buffer[2];
dots_sample = rx_buffer[3];
}
void update_values()
{
// Update values of led array display
// for enhancing visual effect
ud_counter--;
if (ud_counter <= 0)
{
if (bar1_value < bar1_sample)
{
bar1_value++;
}
else if (bar1_value > bar1_sample)
{
bar1_value--;
}
if (bar2_value < bar2_sample)
{
bar2_value++;
}
else if (bar2_value > bar2_sample)
{
bar2_value--;
}
ud_counter = UD_SCALER;
}
}
void update_status()
{
// Flash the STATUS LED when data is active
if (dataActive == 1)
{
da_counter = DA_SCALER;
PORTB &= ~BIT(1); // Turn off LED
dataActive = 0;
}
else if (da_counter > 0)
{
da_counter--;
if (da_counter <= 0)
{
PORTB |= BIT(1); // Turn on LED
}
}
}
void dled_out()
{
byte shift_num;
byte led_data;
byte scan_pos;
scan_pos = PORTC & 0x1F;
switch (scan_pos)
{
case 0x1E:
shift_num = (bar1_value > 8) ? 8 : bar1_value;
led_data = ~(0xFF << shift_num);
break;
case 0x1D:
shift_num = (bar1_value <= 8) ? 0 : bar1_value - 8;
led_data = ~(0xFF << shift_num);
break;
case 0x1B:
shift_num = (bar2_value > 8) ? 8 : bar2_value;
led_data = ~(0xFF << shift_num);
break;
case 0x17:
shift_num = (bar2_value <= 8) ? 0 : bar2_value - 8;
led_data = ~(0xFF << shift_num);
break;
case 0x0F:
led_data = dots_sample;
break;
}
// display
PORTB = ((led_data & 0x0F) << 2) | (PORTB & 0xC3);
PORTD = (led_data & 0xF0) | (PORTD & 0x0F);
}
void init_display()
{
PORTC = 0x1E | (PORTC & 0xE0);
dled_out();
}
void scan_dled()
{
byte scan_signal;
scan_signal = PORTC & 0x1F;
if (scan_signal == 0x0F) // leftmost dled, rewind
{
scan_signal = 0x1E;
}
else
{
scan_signal <<= 1;
scan_signal |= BIT(0);
}
// Clear segment signal first!
PORTB = PORTB & 0xC3;
PORTD = PORTD & 0x0F;
// Scan for next digit
PORTC = scan_signal | (PORTC & 0xE0);
dled_out();
}
void port_init()
{
DDRB = 0x3F; // dled segments (D0-D3)
PORTB = 0x02; // power indicator
DDRC = 0x1F; // PC0-PC4 for dled scanning
PORTC = 0x00;
DDRD = 0xF0; // dled segments (D4-D7)
PORTD = 0x00;
}
//TIMER1 initialize - prescale:8
// WGM: 4) CTC, TOP=OCRnA
// desired value: 1mSec
// actual value: 1.000mSec (0.0%)
void timer1_init()
{
TCCR1B = 0x00; //stop
TCNT1 = 0x0000; //setup
OCR1A = SCALER;
TCCR1A = 0x00;
TCCR1B = 0x0A; //start Timer
TIMSK = 0x10; //enable timer interrupt
}
#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr()
{
//compare occured TCNT1=OCR1A
scan_dled();
update_status();
update_values();
}
//UART0 initialize
// desired baud rate: 19200
// char size: 8 bit
// parity: Disabled
void uart0_init()
{
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = BIT(URSEL) | 0x06;
UBRR = 12; //set baud rate
UCSRB = BIT(RXCIE) | BIT(RXEN) | BIT(TXEN);
}
#pragma interrupt_handler uart0_rx_isr:12
void uart0_rx_isr()
{
byte data, stat;
stat = UCSRA;
data = UDR;
if (stat & (BIT(FE) | BIT(DOR)))
{
rx_counter = 0; // error occured
}
else
{
rx_buffer[rx_counter] = data;
if (rx_counter == 0)
{
if (SOP_CHAR == data) // start of packet
{
rx_counter = 1;
}
}
else if (rx_counter == RX_BUF_SIZE - 1)
{
if (EOP_CHAR == data) // end of packet
{
dataActive = 1;
update_samples();
}
rx_counter = 0;
}
else
{
rx_counter++;
}
}
}
//call this routine to initialize all peripherals
void init_devices()
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer1_init();
uart0_init();
MCUCR = 0x00;
GICR = 0x00;
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void init_vars()
{
rx_counter = 0;
dataActive = 0;
da_counter = 0;
ud_counter = UD_SCALER;
bar1_value = 0;
bar2_value = 0;
bar1_sample = 0;
bar2_sample = 0;
dots_sample = 0x00;
}
void main()
{
init_vars();
init_devices();
init_display();
while(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -