Compare commits
No commits in common. "c0f8cac065634bf5ff77950bfd32578e56f9f1e9" and "52e161f43ba7cfdb0d2ee515967882baa02c359b" have entirely different histories.
c0f8cac065
...
52e161f43b
1 changed files with 30 additions and 153 deletions
|
@ -2,7 +2,6 @@
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
#include <util/twi.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
@ -18,12 +17,6 @@
|
||||||
#define ENC_A (PINB & (1 << PB6))
|
#define ENC_A (PINB & (1 << PB6))
|
||||||
#define ENC_B (PINB & (1 << PB7))
|
#define ENC_B (PINB & (1 << PB7))
|
||||||
|
|
||||||
#define TWI_PORT PORTC
|
|
||||||
#define TWI_SDA PC4
|
|
||||||
#define TWI_SCL PC5
|
|
||||||
|
|
||||||
#define SI5351_ADDRESS (0x60 << 1)
|
|
||||||
|
|
||||||
#define SYM_ENTRY(SYM) { SYM, sizeof(SYM) / 2 }
|
#define SYM_ENTRY(SYM) { SYM, sizeof(SYM) / 2 }
|
||||||
|
|
||||||
static uint8_t EEMEM eeprom_contrast = 8;
|
static uint8_t EEMEM eeprom_contrast = 8;
|
||||||
|
@ -95,9 +88,6 @@ static const __flash uint8_t sym_t[] = { 0x0C, 0x0C, 0xFC, 0xFC, 0x0C, 0x0C,
|
||||||
static const __flash uint8_t sym_u[] = { 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC,
|
static const __flash uint8_t sym_u[] = { 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC,
|
||||||
0x3F, 0x3F, 0x30, 0x30, 0x3F, 0x3F };
|
0x3F, 0x3F, 0x30, 0x30, 0x3F, 0x3F };
|
||||||
|
|
||||||
static const __flash uint8_t sym_underscore[] = { 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x20, 0x20, 0x20, 0x20, 0x20 };
|
|
||||||
|
|
||||||
static const __flash uint8_t sym_invalid[] = { 0x80, 0xE0, 0x98, 0xCC, 0x4C, 0x18, 0xE0, 0x80,
|
static const __flash uint8_t sym_invalid[] = { 0x80, 0xE0, 0x98, 0xCC, 0x4C, 0x18, 0xE0, 0x80,
|
||||||
0x01, 0x07, 0x1F, 0x24, 0x25, 0x1F, 0x07, 0x01};
|
0x01, 0x07, 0x1F, 0x24, 0x25, 0x1F, 0x07, 0x01};
|
||||||
|
|
||||||
|
@ -143,18 +133,7 @@ static const struct symbol symbol_table[] = { SYM_ENTRY(sym_0),
|
||||||
SYM_ENTRY(sym_r),
|
SYM_ENTRY(sym_r),
|
||||||
SYM_ENTRY(sym_s),
|
SYM_ENTRY(sym_s),
|
||||||
SYM_ENTRY(sym_t),
|
SYM_ENTRY(sym_t),
|
||||||
SYM_ENTRY(sym_u),
|
SYM_ENTRY(sym_u) };
|
||||||
SYM_ENTRY(sym_invalid),
|
|
||||||
SYM_ENTRY(sym_invalid),
|
|
||||||
SYM_ENTRY(sym_invalid),
|
|
||||||
SYM_ENTRY(sym_invalid),
|
|
||||||
SYM_ENTRY(sym_invalid),
|
|
||||||
SYM_ENTRY(sym_invalid),
|
|
||||||
SYM_ENTRY(sym_invalid),
|
|
||||||
SYM_ENTRY(sym_invalid),
|
|
||||||
SYM_ENTRY(sym_invalid),
|
|
||||||
SYM_ENTRY(sym_underscore),
|
|
||||||
};
|
|
||||||
|
|
||||||
enum input { cw, ccw, click, hold };
|
enum input { cw, ccw, click, hold };
|
||||||
|
|
||||||
|
@ -187,7 +166,6 @@ static void lcd_write(const uint8_t data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lcd_init(void) {
|
static void lcd_init(void) {
|
||||||
// TODO: Optimize waiting times
|
|
||||||
SPI_DDR |= (1 << LCD_CD) | (1 << LCD_RST);
|
SPI_DDR |= (1 << LCD_CD) | (1 << LCD_RST);
|
||||||
_delay_ms(1);
|
_delay_ms(1);
|
||||||
SPI_PORT |= (1 << LCD_RST);
|
SPI_PORT |= (1 << LCD_RST);
|
||||||
|
@ -222,12 +200,12 @@ static void lcd_update_backlight(void) {
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
case 5:
|
case 5:
|
||||||
TCCR0B = 0x0C; // Prescaler = 256;
|
TCCR0B = 0x0C; // prescaler = 256;
|
||||||
DDRD |= (1 << PD5);
|
DDRD |= (1 << PD5);
|
||||||
OCR0B = value_backlight - 1;
|
OCR0B = value_backlight - 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
TCCR0B = 0x0B; // Prescaler = 64;
|
TCCR0B = 0x0B; // prescaler = 64;
|
||||||
DDRD |= (1 << PD5);
|
DDRD |= (1 << PD5);
|
||||||
OCR0B = value_backlight - 4;
|
OCR0B = value_backlight - 4;
|
||||||
break;
|
break;
|
||||||
|
@ -302,7 +280,6 @@ static void lcd_write_integer_page(const uint8_t integer,
|
||||||
uint16_t comperator = 1;
|
uint16_t comperator = 1;
|
||||||
|
|
||||||
for (; comperator <= integer; comperator *= 10, input_digits++);
|
for (; comperator <= integer; comperator *= 10, input_digits++);
|
||||||
|
|
||||||
for (int8_t i = digits - input_digits; i > 0; i--) {
|
for (int8_t i = digits - input_digits; i > 0; i--) {
|
||||||
lcd_write_kerning(2, invert);
|
lcd_write_kerning(2, invert);
|
||||||
lcd_write_digit_page(0, page, invert);
|
lcd_write_digit_page(0, page, invert);
|
||||||
|
@ -335,98 +312,7 @@ static void lcd_splash(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void twi_error(void) {
|
static void lcd_home(void) {
|
||||||
lcd_fill(0xFF);
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 2; i++) {
|
|
||||||
lcd_move_cursor(0, i);
|
|
||||||
lcd_write_string_page("TW_STATUS:\0", i, true);
|
|
||||||
lcd_write_kerning(2, true);
|
|
||||||
lcd_write_integer_page(TW_STATUS, 3, i, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 2; i++) {
|
|
||||||
lcd_move_cursor(0, i + 2);
|
|
||||||
lcd_write_string_page("TW_DATA:\0", i, true);
|
|
||||||
lcd_write_kerning(16, true);
|
|
||||||
lcd_write_integer_page(TWDR, 3, i, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void twi_start(void) {
|
|
||||||
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // Start transmission
|
|
||||||
while (!(TWCR & (1 << TWINT))); // Wait until start is transmitted
|
|
||||||
|
|
||||||
if (TW_STATUS != TW_START) // Check status
|
|
||||||
twi_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t twi_transmit(const uint8_t data) {
|
|
||||||
TWDR = data;
|
|
||||||
TWCR = (1 << TWINT) | (1 << TWEN); // Transmit data
|
|
||||||
while (!(TWCR & (1 << TWINT))); // Wait until data is transmitted
|
|
||||||
|
|
||||||
return TW_STATUS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t twi_receive(void) {
|
|
||||||
TWCR = (1 << TWINT) | (1 << TWEN); // Receive data
|
|
||||||
while (!(TWCR & (1 << TWINT))); // Wait until data is received
|
|
||||||
|
|
||||||
return TW_STATUS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void twi_stop(void) {
|
|
||||||
TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t twi_read_register(const uint8_t address,
|
|
||||||
const uint8_t reg) {
|
|
||||||
twi_start();
|
|
||||||
|
|
||||||
if (twi_transmit(address) != TW_MT_SLA_ACK)
|
|
||||||
twi_error();
|
|
||||||
|
|
||||||
if (twi_transmit(reg) != TW_MT_DATA_ACK)
|
|
||||||
twi_error();
|
|
||||||
|
|
||||||
twi_stop();
|
|
||||||
|
|
||||||
_delay_us(2);
|
|
||||||
|
|
||||||
twi_start();
|
|
||||||
|
|
||||||
if (twi_transmit(address + 1) != TW_MR_SLA_ACK)
|
|
||||||
twi_error();
|
|
||||||
|
|
||||||
if (twi_receive() != TW_MR_DATA_NACK)
|
|
||||||
twi_error();
|
|
||||||
|
|
||||||
twi_stop();
|
|
||||||
|
|
||||||
return TWDR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void twi_write_register(const uint8_t address,
|
|
||||||
const uint8_t reg,
|
|
||||||
const uint8_t data) {
|
|
||||||
twi_start();
|
|
||||||
|
|
||||||
if (twi_transmit(address) != TW_MT_SLA_ACK)
|
|
||||||
twi_error();
|
|
||||||
|
|
||||||
if (twi_transmit(reg) != TW_MT_DATA_ACK)
|
|
||||||
twi_error();
|
|
||||||
|
|
||||||
if (twi_transmit(data) != TW_MT_DATA_ACK)
|
|
||||||
twi_error();
|
|
||||||
|
|
||||||
twi_stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw_home(void) {
|
|
||||||
lcd_fill(0x00);
|
lcd_fill(0x00);
|
||||||
|
|
||||||
bool ch1_selected = false;
|
bool ch1_selected = false;
|
||||||
|
@ -468,7 +354,7 @@ static void draw_home(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_setup(void) {
|
static void lcd_setup(void) {
|
||||||
lcd_fill(0x00);
|
lcd_fill(0x00);
|
||||||
|
|
||||||
bool contrast_selected = false;
|
bool contrast_selected = false;
|
||||||
|
@ -507,8 +393,7 @@ static void draw_setup(void) {
|
||||||
lcd_write_string_page("CONTRAST:\0", i, contrast_selected);
|
lcd_write_string_page("CONTRAST:\0", i, contrast_selected);
|
||||||
lcd_write_kerning(2, contrast_selected);
|
lcd_write_kerning(2, contrast_selected);
|
||||||
lcd_write_kerning(16, false);
|
lcd_write_kerning(16, false);
|
||||||
lcd_write_integer_page(value_contrast, 2, i,
|
lcd_write_integer_page(value_contrast, 2, i, change_contrast_selected);
|
||||||
change_contrast_selected);
|
|
||||||
lcd_write_kerning(2, change_contrast_selected);
|
lcd_write_kerning(2, change_contrast_selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,8 +402,7 @@ static void draw_setup(void) {
|
||||||
lcd_write_string_page("BACKLIGHT:\0", i, backlight_selected);
|
lcd_write_string_page("BACKLIGHT:\0", i, backlight_selected);
|
||||||
lcd_write_kerning(2, backlight_selected);
|
lcd_write_kerning(2, backlight_selected);
|
||||||
lcd_write_kerning(5, false);
|
lcd_write_kerning(5, false);
|
||||||
lcd_write_integer_page(value_backlight, 3, i,
|
lcd_write_integer_page(value_backlight, 3, i, change_backlight_selected);
|
||||||
change_backlight_selected);
|
|
||||||
lcd_write_kerning(2, change_backlight_selected);
|
lcd_write_kerning(2, change_backlight_selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,7 +416,7 @@ static void draw_setup(void) {
|
||||||
static void change_state(const enum state new_state) {
|
static void change_state(const enum state new_state) {
|
||||||
switch (new_state) {
|
switch (new_state) {
|
||||||
case home:
|
case home:
|
||||||
draw_home();
|
lcd_home();
|
||||||
current_state = home;
|
current_state = home;
|
||||||
break;
|
break;
|
||||||
case ch1:
|
case ch1:
|
||||||
|
@ -543,7 +427,7 @@ static void change_state(const enum state new_state) {
|
||||||
break;
|
break;
|
||||||
case setup:
|
case setup:
|
||||||
setup_state = contrast;
|
setup_state = contrast;
|
||||||
draw_setup();
|
lcd_setup();
|
||||||
current_state = setup;
|
current_state = setup;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -555,13 +439,13 @@ static void update_home(const enum input event) {
|
||||||
home_state++;
|
home_state++;
|
||||||
if (home_state > setup)
|
if (home_state > setup)
|
||||||
home_state = ch1;
|
home_state = ch1;
|
||||||
draw_home();
|
lcd_home();
|
||||||
break;
|
break;
|
||||||
case ccw:
|
case ccw:
|
||||||
home_state--;
|
home_state--;
|
||||||
if (home_state > setup)
|
if (home_state > setup)
|
||||||
home_state = setup;
|
home_state = setup;
|
||||||
draw_home();
|
lcd_home();
|
||||||
break;
|
break;
|
||||||
case click:
|
case click:
|
||||||
change_state(home_state);
|
change_state(home_state);
|
||||||
|
@ -595,7 +479,7 @@ static void update_setup(const enum input event) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
draw_setup();
|
lcd_setup();
|
||||||
break;
|
break;
|
||||||
case ccw:
|
case ccw:
|
||||||
switch (setup_state) {
|
switch (setup_state) {
|
||||||
|
@ -619,17 +503,17 @@ static void update_setup(const enum input event) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
draw_setup();
|
lcd_setup();
|
||||||
break;
|
break;
|
||||||
case click:
|
case click:
|
||||||
switch (setup_state) {
|
switch (setup_state) {
|
||||||
case contrast:
|
case contrast:
|
||||||
setup_state = change_contrast;
|
setup_state = change_contrast;
|
||||||
draw_setup();
|
lcd_setup();
|
||||||
break;
|
break;
|
||||||
case backlight:
|
case backlight:
|
||||||
setup_state = change_backlight;
|
setup_state = change_backlight;
|
||||||
draw_setup();
|
lcd_setup();
|
||||||
break;
|
break;
|
||||||
case back:
|
case back:
|
||||||
change_state(home);
|
change_state(home);
|
||||||
|
@ -637,12 +521,12 @@ static void update_setup(const enum input event) {
|
||||||
case change_contrast:
|
case change_contrast:
|
||||||
eeprom_update_byte(&eeprom_contrast, value_contrast);
|
eeprom_update_byte(&eeprom_contrast, value_contrast);
|
||||||
setup_state = contrast;
|
setup_state = contrast;
|
||||||
draw_setup();
|
lcd_setup();
|
||||||
break;
|
break;
|
||||||
case change_backlight:
|
case change_backlight:
|
||||||
eeprom_update_byte(&eeprom_backlight, value_backlight);
|
eeprom_update_byte(&eeprom_backlight, value_backlight);
|
||||||
setup_state = backlight;
|
setup_state = backlight;
|
||||||
draw_setup();
|
lcd_setup();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -657,13 +541,13 @@ static void update_setup(const enum input event) {
|
||||||
setup_state = contrast;
|
setup_state = contrast;
|
||||||
value_contrast = eeprom_read_byte(&eeprom_contrast);
|
value_contrast = eeprom_read_byte(&eeprom_contrast);
|
||||||
lcd_update_contrast();
|
lcd_update_contrast();
|
||||||
draw_setup();
|
lcd_setup();
|
||||||
break;
|
break;
|
||||||
case change_backlight:
|
case change_backlight:
|
||||||
setup_state = backlight;
|
setup_state = backlight;
|
||||||
value_backlight = eeprom_read_byte(&eeprom_backlight);
|
value_backlight = eeprom_read_byte(&eeprom_backlight);
|
||||||
lcd_update_backlight();
|
lcd_update_backlight();
|
||||||
draw_setup();
|
lcd_setup();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -691,9 +575,6 @@ static void update_state(const enum input event) {
|
||||||
ISR(PCINT0_vect) {
|
ISR(PCINT0_vect) {
|
||||||
cli();
|
cli();
|
||||||
|
|
||||||
// Dechatter
|
|
||||||
_delay_ms(3);
|
|
||||||
|
|
||||||
switch (enc) {
|
switch (enc) {
|
||||||
case 0:
|
case 0:
|
||||||
if (ENC_A && !ENC_B)
|
if (ENC_A && !ENC_B)
|
||||||
|
@ -727,16 +608,16 @@ ISR(PCINT0_vect) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: proper dechattering
|
||||||
|
_delay_ms(3);
|
||||||
|
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encoder button interrupt
|
// encoder button interrupt
|
||||||
ISR(PCINT1_vect) {
|
ISR(PCINT1_vect) {
|
||||||
cli();
|
cli();
|
||||||
|
|
||||||
// Debounce
|
|
||||||
_delay_ms(2);
|
|
||||||
|
|
||||||
if (PINC & (1 << PC0)) { // Release
|
if (PINC & (1 << PC0)) { // Release
|
||||||
if (TCCR1B & (1 << CS10)) // If release before hold
|
if (TCCR1B & (1 << CS10)) // If release before hold
|
||||||
update_state(click); // Switch to selected state
|
update_state(click); // Switch to selected state
|
||||||
|
@ -748,6 +629,9 @@ ISR(PCINT1_vect) {
|
||||||
TCCR1B |= (1 << CS11) | (1 << CS10); // Enable Timer/Counter1
|
TCCR1B |= (1 << CS11) | (1 << CS10); // Enable Timer/Counter1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Proper debouncing
|
||||||
|
_delay_ms(3);
|
||||||
|
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -766,12 +650,13 @@ int main(void) {
|
||||||
value_contrast = eeprom_read_byte(&eeprom_contrast);
|
value_contrast = eeprom_read_byte(&eeprom_contrast);
|
||||||
value_backlight = eeprom_read_byte(&eeprom_backlight);
|
value_backlight = eeprom_read_byte(&eeprom_backlight);
|
||||||
|
|
||||||
// Init backlight
|
// Init backlight: FastPWM: 1.25kHz
|
||||||
|
// TODO: Try to get the backlit even more dim
|
||||||
TCCR0A |= (1 << WGM01) | (1 << WGM00) | (1 << COM0B1);
|
TCCR0A |= (1 << WGM01) | (1 << WGM00) | (1 << COM0B1);
|
||||||
OCR0A = 255;
|
OCR0A = 255;
|
||||||
lcd_update_backlight();
|
lcd_update_backlight();
|
||||||
|
|
||||||
// SPI and LCD init
|
// SPI setup
|
||||||
spi_init();
|
spi_init();
|
||||||
lcd_init();
|
lcd_init();
|
||||||
|
|
||||||
|
@ -789,19 +674,11 @@ int main(void) {
|
||||||
OCR1A = 65535;
|
OCR1A = 65535;
|
||||||
TIMSK1 |= (1 << OCIE1A); // Enable match compare A
|
TIMSK1 |= (1 << OCIE1A); // Enable match compare A
|
||||||
|
|
||||||
// Show splash screen
|
// Show splash screen and load the menu
|
||||||
lcd_splash();
|
lcd_splash();
|
||||||
_delay_ms(2000);
|
_delay_ms(2000);
|
||||||
|
|
||||||
// Load the menu
|
|
||||||
change_state(current_state);
|
change_state(current_state);
|
||||||
|
|
||||||
// Set TWI bit rate to 200kHz
|
|
||||||
TWBR = 12;
|
|
||||||
|
|
||||||
(void) &twi_read_register;
|
|
||||||
(void) &twi_write_register;
|
|
||||||
|
|
||||||
// Enable interrupts
|
// Enable interrupts
|
||||||
sei();
|
sei();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue