working on serial syncronization for programming eeprom

This commit is contained in:
Brett Weiland 2022-09-27 16:14:28 -05:00
parent 7b006d6f20
commit 94304b11e7
22 changed files with 336 additions and 172 deletions

BIN
docs/atmega328p.pdf Normal file

Binary file not shown.

BIN
docs/mega2560_schematic.pdf Normal file

Binary file not shown.

BIN
docs/nano.pdf Normal file

Binary file not shown.

View File

@ -1,6 +1,12 @@
#include <avr/io.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <util/delay.h>
#include "i2c.h" #include "i2c.h"
#include "br24t_eeprom_driver.h" #include "br24t_eeprom_driver.h"
#include "uart.h"
#include "pins.h"
#include "debug.h"
#define EEPROM_ADDR 0x57 #define EEPROM_ADDR 0x57
#define EEPROM_PAGE_SIZE 64 #define EEPROM_PAGE_SIZE 64
@ -13,29 +19,24 @@
#define PAGE_WRITE_CORRUPTED 0x01 #define PAGE_WRITE_CORRUPTED 0x01
#define PAGE_WRITE_UNKNOWN_ERROR 0xff #define PAGE_WRITE_UNKNOWN_ERROR 0xff
//we need another function cause it's got a 16 bit register address
#ifdef FLASH_EEPROM #ifdef FLASH_EEPROM
void flash_eeprom() { void flash_eeprom() {
uint16_t data_len; uint16_t page_len;
uint32_t syn = 0;
uint8_t on_byte; uint8_t on_byte;
uint8_t eeprom_buffer_out[EEPROM_PAGE_SIZE]; uint8_t eeprom_buffer_out[EEPROM_PAGE_SIZE];
uint8_t eeprom_buffer_in[EEPROM_PAGE_SIZE]; uint8_t eeprom_buffer_in[EEPROM_PAGE_SIZE];
while(syn != MAGIC_SYN) fread(&syn, 4, 1, stdin); //not sure we _really_ need to do this? fread(&page_len, 1, 1, stdin);
//this feels ugly for(int page = 0; page < page_len; page -= page_len) {
syn = MAGIC_ACK;
fwrite(&syn, 4, 1, stdout);
//get amount of data we'll be using
data_len = uart_recvbyte();
data_len |= (uart_recvbyte() >> 8);
for(int page = 0; page < (data_len / EEPROM_PAGE_SIZE); data_len -= EEPROM_PAGE_SIZE) {
fread(eeprom_buffer_out, EEPROM_PAGE_SIZE, 1, stdin); fread(eeprom_buffer_out, EEPROM_PAGE_SIZE, 1, stdin);
//fread(eeprom_buffer_out, 11, 1, stdin);
fputc(PAGE_WRITE_CORRUPTED, stdout);
DEBUG_LED_ON();
for(;;);
i2c_start(EEPROM_I2C_ADDR, I2C_READ); i2c_start(EEPROM_I2C_ADDR, I2C_READ);
i2c_send((uint8_t)(page * EEPROM_PAGE_SIZE) & 0xff); i2c_send((uint8_t)(page * EEPROM_PAGE_SIZE) & 0xff);
@ -52,9 +53,9 @@ void flash_eeprom() {
eeprom_buffer_in[on_byte] = i2c_recv(); eeprom_buffer_in[on_byte] = i2c_recv();
i2c_stop(); i2c_stop();
if(memcmp(eeprom_buffer_in, eeprom_buffer_out, EEPROM_PAGE_SIZE)) { if(!memcmp(eeprom_buffer_in, eeprom_buffer_out, EEPROM_PAGE_SIZE)) {
fputc(PAGE_WRITE_CORRUPTED, stdout); fputc(PAGE_WRITE_CORRUPTED, stdout);
error(); for(;;); //TODO error here
} }
fputc(PAGE_WRITE_OK, stdout); fputc(PAGE_WRITE_OK, stdout);
} }

View File

@ -4,7 +4,7 @@
#include <stdint.h> #include <stdint.h>
#include "i2c.h" #include "i2c.h"
#define EEPROM_I2C_ADDR 0x50 //fix to represent custom address setting #define EEPROM_I2C_ADDR 0x50
#ifdef FLASH_EEPROM #ifdef FLASH_EEPROM
@ -13,7 +13,8 @@ void flash_eeprom();
typedef uint16_t EEPROM_ADDR; typedef uint16_t EEPROM_ADDR;
#define EEPROM_READBYTE(addr) i2c_read_reg_addr16(EEPROM_I2C_ADDR, addr); #define EEPROM_READBYTE(addr) i2c_read_reg_addr16(EEPROM_I2C_ADDR, addr)
#define EEPROM_WRITEBYTE(addr, data) i2c_write_reg_addr16(EEPROM_I2C_ADDR, addr, data);
#endif #endif

View File

@ -110,5 +110,31 @@
"-Wall" "-Wall"
], ],
"file": "paint.c" "file": "paint.c"
},
{
"directory": "/home/indigo/projects/watch/src",
"arguments": [
"/home/indigo/packs/avr8-gnu-toolchain-linux_x86_64/bin/avr-gcc",
"-mmcu=atmega328p",
"-I",
"/home/indigo/packs/avr8-gnu-toolchain-linux_x86_64/avr/include",
"-o",
"compiled_payload.elf",
"-DDEBUG_BUILD=1",
"-DBAUD=9600",
"-DF_CPU=16000000",
"-Wall",
"-O1",
"main.c",
"debug.c",
"i2c.c",
"ssd1306_display_driver.c",
"uart.c",
"br24t_eeprom_driver.c",
"paint.c",
"pcf_clock_driver.c",
"-Wall"
],
"file": "pcf_clock_driver.c"
} }
] ]

View File

@ -26,8 +26,8 @@ page_cnt = 4
# also note we have no protection from using unsed chars, I can't let this project # also note we have no protection from using unsed chars, I can't let this project
# get to big for litteraly no reason # get to big for litteraly no reason
header.write("/** GENERATED BY EEPROM COMPILER SCRIPT **/\n\n") header.write("/** GENERATED BY EEPROM COMPILER SCRIPT **/\r\n\r\n")
header.write("// FONTS\n") header.write("// FONTS\r\n")
for file in os.listdir("{}/fonts/".format(data_path)): for file in os.listdir("{}/fonts/".format(data_path)):
path = "{}/fonts/{}".format(data_path, file) path = "{}/fonts/{}".format(data_path, file)
@ -36,22 +36,22 @@ for file in os.listdir("{}/fonts/".format(data_path)):
font_bdf = BdfFontFile.BdfFontFile(font_fd) font_bdf = BdfFontFile.BdfFontFile(font_fd)
font_name = file.split('.')[0].capitalize() font_name = file.split('.')[0].capitalize()
header.write("#define FONT_{}_ADDR\t0x{:04x}\n".format(font_name, output.tell())) header.write("#define FONT_{}_ADDR\t0x{:04x}\r\n".format(font_name, output.tell()))
first_char = False first_char = False
for char in enumerate(font_bdf.glyph): for char in enumerate(font_bdf.glyph):
if char[1]: if char[1]:
if not first_char: if not first_char:
first_char = True first_char = True
header.write(("#define FONT_{}_FIRST_CHAR\t{}\n" header.write(("#define FONT_{}_FIRST_CHAR\t{}\r\n"
"#define FONT_{}_WIDTH\t{}\n" "#define FONT_{}_WIDTH\t{}\r\n"
"#define FONT_{}_HEIGHT\t{}\n").format( "#define FONT_{}_HEIGHT\t{}\r\n").format(
font_name, char[0], font_name, char[0],
font_name, char[1][-1].size[0], font_name, char[1][-1].size[0],
font_name, char[1][-1].size[1])) font_name, char[1][-1].size[1]))
output.write(char[1][-1].tobytes('raw')) output.write(char[1][-1].tobytes('raw'))
header.write("\n\n// IMAGES\n#define IMG_BEGIN\t0x{:04x}\n".format(output.tell())) header.write("\r\n\r\n// IMAGES\r\n#define IMG_BEGIN\t0x{:04x}\r\n".format(output.tell()))
image_cnt = 0 image_cnt = 0
@ -65,9 +65,9 @@ for file in os.listdir("{}/images/".format(data_path)):
image_bitmap_remapped = [] image_bitmap_remapped = []
image = Image.open(image_fd) image = Image.open(image_fd)
if not image.mode == 'RGB': if not image.mode == 'RGB':
print("this script only compiles RGB formatted photos! (I'm lazy\n") print("this script only compiles RGB formatted photos! (I'm lazy\r\n")
exit(1) exit(1)
header.write("#define IMG_{}_ADDR\t0x{:04x}\n".format( header.write("#define IMG_{}_ADDR\t0x{:04x}\r\n".format(
file.split('.')[0].capitalize(), file.split('.')[0].capitalize(),
output.tell())) output.tell()))
for byte in range(0, len(image.tobytes()), 3): for byte in range(0, len(image.tobytes()), 3):
@ -98,7 +98,7 @@ for file in os.listdir("{}/images/".format(data_path)):
((bit % 8) - (extract_bit % 8)) ((bit % 8) - (extract_bit % 8))
[output.write(byte.to_bytes(1, 'big')) for byte in image_bitmap_remapped] [output.write(byte.to_bytes(1, 'big')) for byte in image_bitmap_remapped]
header.write("#define IMG_COUNT\t{}\n\n".format(image_cnt)) header.write("#define IMG_COUNT\t{}\r\n\r\n".format(image_cnt))
@ -107,7 +107,7 @@ print("EEPROM used: {}% ({} out of {} bits)".format(
output.tell(), eeprom_length)) output.tell(), eeprom_length))
if(output.tell() > eeprom_length): if(output.tell() > eeprom_length):
print("WARNING: You've used more eeprom then there is available!\n") print("WARNING: You've used more eeprom then there is available!\r\n")
output.close() output.close()
header.close() header.close()

View File

@ -1,10 +1,71 @@
#include <avr/io.h> #include <avr/io.h>
#include <stdio.h> #include <stdio.h>
#include <util/delay.h> #include <util/delay.h>
#include "ssd1306_display_driver.h"
#include "i2c.h"
#include "debug.h" #include "debug.h"
#include "br24t_eeprom_driver.h"
//this is used elsewhere (only one file) besides debug but kind of gross, maybe move to a header or something
#define SSD1306_ADDR 0x3c
#define SSD1306_CMD_REG 0x00
#define SSD1306_DATA_REG 0x40
#define SCREEN_PAGE_CNT SCREEN_RES_Y / 8
#define I2C_WRITE 0
#define I2C_READ 1
void scroll_test() {
//sets scroll area to whole screen
i2c_write_reg_multi(SSD1306_ADDR, SSD1306_CMD_REG, 3, (uint8_t[]){0xa3, 0x00, 0x20});
//set up scroll options
i2c_write_reg_multi(SSD1306_ADDR, SSD1306_CMD_REG, 6, (uint8_t[]){0x29, 0x00, 0x00, 0x00, 0x04, 0x00});
//actually activate scroll
i2c_write_reg_multi(SSD1306_ADDR, SSD1306_CMD_REG, 6, (uint8_t[]){0x2f});
}
void screen_lowlvl_testdraw() {
unsigned int on_pix;
unsigned int on_page;
printf("running screen time tests\r\n");
printf("generating test image...\r\n");
for(on_pix = 0; on_pix < sizeof(screen_buffer); on_pix++)
screen_buffer[on_pix] = ((uint8_t)0xaa << (on_pix % 8));
printf("page mode, individual byte per i2c call...\r\n");
for(on_page = 0; on_page < SCREEN_PAGE_CNT; on_page++) {
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0xb0 + on_page);
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0x00);
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0x10);
for(on_pix = 0; on_pix < SCREEN_RES_X; on_pix++)
i2c_write_reg(SSD1306_ADDR, SSD1306_DATA_REG, screen_buffer[(on_page * 8) + on_pix]);
}
printf("page mode, 1 page per i2c call...\r\n");
for(on_page = 0; on_page < SCREEN_PAGE_CNT; on_page++) {
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0xb0 + on_page);
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0x00);
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0x10);
i2c_write_reg_multi(SSD1306_ADDR, SSD1306_DATA_REG, SCREEN_RES_X, &screen_buffer[on_page * SCREEN_RES_X]);
}
printf("screen test draw done!\n");
}
void uart_echo() {
char buff;
for(;;) {
fread(&buff, 1, 1, stdin);
fwrite(&buff, 1, 1, stdout);
}
}
void test_clock() {
printf("The time is %s, waiting 5 mintes...\r\n", "not implimented");
_delay_ms(300000);
printf("The time is now %s, hope your RTC clock works\r\n", "not implimented");
}
/* /*
@ -27,5 +88,14 @@ void test_timer() {
start = TCNT1; start = TCNT1;
_delay_ms(1000); _delay_ms(1000);
end = TCNT1; end = TCNT1;
printf("1 second is %u ticks\n", end - start); printf("1 second is %u ticks\r\n", end - start);
}
void eeprom_testbyte() {
uint8_t data_in = 0xde;
uint8_t data_out = 0;
printf("writing 0x%x to eeprom...\r\n", data_in);
EEPROM_WRITEBYTE(0x0000, data_in);
data_out = EEPROM_READBYTE(0x0000);
printf("byte read from eeprom: 0x%x\r\n", data_out);
} }

View File

@ -4,11 +4,20 @@
#include <stdio.h> #include <stdio.h>
#include <avr/io.h> #include <avr/io.h>
#include "uart.h" #include "uart.h"
#include "pins.h"
void timer_init(); void timer_init();
void test_timer(); void test_timer();
void scroll_test();
void screen_lowlvl_testdraw();
void uart_echo();
void test_clock();
void eeprom_testbyte();
unsigned int ticks_to_seconds(); unsigned int ticks_to_seconds();
#define DEBUG_LED_ON() LED_DEBUG_PORT |= _BV(LED_DEBUG)
#define DEBUG_LED_OFF() LED_DEBUG_PORT &= ~(_BV(LED_DEBUG))
#endif #endif

View File

@ -1,47 +1,47 @@
/** GENERATED BY EEPROM COMPILER SCRIPT **/ /** GENERATED BY EEPROM COMPILER SCRIPT **/
// FONTS // FONTS
#define FONT_5thelement_ADDR 0x0000 #define FONT_5thelement_ADDR 0x0000
#define FONT_5thelement_FIRST_CHAR 32 #define FONT_5thelement_FIRST_CHAR 32
#define FONT_5thelement_WIDTH 4 #define FONT_5thelement_WIDTH 4
#define FONT_5thelement_HEIGHT 5 #define FONT_5thelement_HEIGHT 5
#define FONT_4thd_ADDR 0x01db #define FONT_Bitbuntu_ADDR 0x01db
#define FONT_4thd_FIRST_CHAR 32 #define FONT_Bitbuntu_FIRST_CHAR 32
#define FONT_4thd_WIDTH 4 #define FONT_Bitbuntu_WIDTH 0
#define FONT_4thd_HEIGHT 4 #define FONT_Bitbuntu_HEIGHT 0
#define FONT_Bitocra-13-full_ADDR 0x0357 #define FONT_Bitocra-13_ADDR 0x067b
#define FONT_Bitocra-13-full_FIRST_CHAR 32 #define FONT_Bitocra-13_FIRST_CHAR 32
#define FONT_Bitocra-13-full_WIDTH 7 #define FONT_Bitocra-13_WIDTH 7
#define FONT_Bitocra-13-full_HEIGHT 13 #define FONT_Bitocra-13_HEIGHT 13
#define FONT_Bitocra-13_ADDR 0x0cf0 #define FONT_Bitocra-13-full_ADDR 0x1014
#define FONT_Bitocra-13_FIRST_CHAR 32 #define FONT_Bitocra-13-full_FIRST_CHAR 32
#define FONT_Bitocra-13_WIDTH 7 #define FONT_Bitocra-13-full_WIDTH 7
#define FONT_Bitocra-13_HEIGHT 13 #define FONT_Bitocra-13-full_HEIGHT 13
#define FONT_Bitocra_ADDR 0x1689 #define FONT_4thd_ADDR 0x19ad
#define FONT_Bitocra_FIRST_CHAR 32 #define FONT_4thd_FIRST_CHAR 32
#define FONT_Bitocra_WIDTH 0 #define FONT_4thd_WIDTH 4
#define FONT_Bitocra_HEIGHT 0 #define FONT_4thd_HEIGHT 4
#define FONT_Bitbuntu_ADDR 0x1b1d #define FONT_Bitocra_ADDR 0x1b29
#define FONT_Bitbuntu_FIRST_CHAR 32 #define FONT_Bitocra_FIRST_CHAR 32
#define FONT_Bitbuntu_WIDTH 0 #define FONT_Bitocra_WIDTH 0
#define FONT_Bitbuntu_HEIGHT 0 #define FONT_Bitocra_HEIGHT 0
#define FONT_Bitocra-full_ADDR 0x1fbd #define FONT_Bitocra7_ADDR 0x1fbd
#define FONT_Bitocra-full_FIRST_CHAR 32 #define FONT_Bitocra7_FIRST_CHAR 0
#define FONT_Bitocra-full_WIDTH 6 #define FONT_Bitocra7_WIDTH 4
#define FONT_Bitocra-full_HEIGHT 11 #define FONT_Bitocra7_HEIGHT 7
#define FONT_Bitbuntu-full_ADDR 0x27e7 #define FONT_Bitbuntu-full_ADDR 0x24fd
#define FONT_Bitbuntu-full_FIRST_CHAR 32 #define FONT_Bitbuntu-full_FIRST_CHAR 32
#define FONT_Bitbuntu-full_WIDTH 6 #define FONT_Bitbuntu-full_WIDTH 6
#define FONT_Bitbuntu-full_HEIGHT 10 #define FONT_Bitbuntu-full_HEIGHT 10
#define FONT_Bitocra7_ADDR 0x2f53 #define FONT_Bitocra-full_ADDR 0x2c69
#define FONT_Bitocra7_FIRST_CHAR 0 #define FONT_Bitocra-full_FIRST_CHAR 32
#define FONT_Bitocra7_WIDTH 4 #define FONT_Bitocra-full_WIDTH 6
#define FONT_Bitocra7_HEIGHT 7 #define FONT_Bitocra-full_HEIGHT 11
// IMAGES // IMAGES
#define IMG_BEGIN 0x3493 #define IMG_BEGIN 0x3493
#define IMG_Test_image_2_ADDR 0x3493 #define IMG_Test_image_2_ADDR 0x3493
#define IMG_Test_image_1_ADDR 0x3693 #define IMG_Test_image_1_ADDR 0x3693
#define IMG_COUNT 2 #define IMG_COUNT 2

0
src/eeprom_dump Normal file
View File

View File

@ -37,7 +37,7 @@
* *
*/ */
void error() {} void error() { }
void i2c_init() { void i2c_init() {
TWBR = 12; TWBR = 12;
@ -48,29 +48,30 @@ void i2c_init() {
void i2c_start(uint8_t addr, bool rw) { void i2c_start(uint8_t addr, bool rw) {
TWCR = (_BV(TWSTA) | _BV(TWEN) | _BV(TWINT)); //send start signal TWCR = (_BV(TWSTA) | _BV(TWEN) | _BV(TWINT)); //send start signal
loop_until_bit_is_set(TWCR, TWINT); loop_until_bit_is_set(TWCR, TWINT);
if((TWSR & 0xf8) != TW_START) { if(((TWSR & 0xf8) != (TW_START)) && ((TWSR & 0xf8) != (TW_REP_START))) {
#ifdef DEBUG_BUILD #ifdef DEBUG_BUILD
printf("Couldn't set start condition?\n"); printf("Couldn't set start condition? TWSR: 0x%x\r\n", TWSR & 0xf8);
#endif #endif
error(); error();
} }
TWDR = (addr << 1) | rw; TWDR = (addr << 1) | rw;
TWCR = _BV(TWINT) | _BV(TWEN); TWCR = _BV(TWINT) | _BV(TWEN);
loop_until_bit_is_set(TWCR, TWINT); loop_until_bit_is_set(TWCR, TWINT);
if((TWSR & 0xf8) != TW_MT_SLA_ACK) { if(((TWSR & 0xf8) != (TW_MT_SLA_ACK)) && (TWSR & 0xf8) != (TW_MR_SLA_ACK)) {
#ifdef DEBUG_BUILD #ifdef DEBUG_BUILD
printf("unhandled NACK in address transmission\ printf("unhandled NACK in address transmission\
TWCR: 0x%x\ TWCR: 0x%x\
TWSR: 0x%x\n", TWCR, (TWSR & ~(0b11))); TWSR: 0x%x\r\n", TWCR, (TWSR & ~(0b11)));
#endif #endif
error(); error();
} }
} }
void i2c_stop() { TWCR = (_BV(TWSTO) | _BV(TWEN) | _BV(TWINT)); } void i2c_stop() { TWCR = (_BV(TWSTO) | _BV(TWEN) | _BV(TWINT)); _delay_ms(500); }
void i2c_send(uint8_t byte) { void i2c_send(uint8_t byte) {
TWDR = byte; //fist packet is address TWDR = byte; //fist packet is address
@ -81,7 +82,7 @@ void i2c_send(uint8_t byte) {
#ifdef DEBUG_BUILD #ifdef DEBUG_BUILD
printf("unhandled NACK in data transmission\ printf("unhandled NACK in data transmission\
TWCR: 0x%x\ TWCR: 0x%x\
TWSR: 0x%x\n", TWCR, (TWSR & ~(0b11))); TWSR: 0x%x\r\n", TWCR, (TWSR & ~(0b11)));
#endif #endif
error(); error();
} }
@ -89,11 +90,14 @@ void i2c_send(uint8_t byte) {
uint8_t i2c_recv() { uint8_t i2c_recv() {
uint8_t value; uint8_t value;
TWCR = _BV(TWINT) | _BV(TWEN);
loop_until_bit_is_set(TWCR, TWINT); loop_until_bit_is_set(TWCR, TWINT);
value = TWDR; value = TWDR;
if((TWSR & 0xf8) != TW_MR_SLA_ACK) { //the eeprom supposedly doesn't return an ack here,
//as it should (according to its datasheet), but it still works?
if(((TWSR & 0xf8) != TW_MR_DATA_ACK) && ((TWSR & 0xf8) != TW_MR_DATA_NACK)) {
#ifdef DEBUG_BUILD #ifdef DEBUG_BUILD
printf("Error recieving byte from i2c device\n"); printf("Error recieving byte from i2c device: 0x%x\r\n", TWSR & 0xf8);
#endif #endif
error(); error();
} }
@ -128,3 +132,11 @@ void i2c_write_reg_multi(uint8_t device_addr, uint8_t device_reg, size_t len, ui
for(size_t on_byte = 0; on_byte < len; on_byte++) i2c_send(values[on_byte]); for(size_t on_byte = 0; on_byte < len; on_byte++) i2c_send(values[on_byte]);
i2c_stop(); i2c_stop();
} }
void i2c_write_reg_addr16(uint8_t device_addr, uint16_t device_reg, uint8_t data) {
i2c_start(device_addr, I2C_WRITE);
i2c_send((uint8_t)device_reg & 0xff);
i2c_send((uint8_t)device_reg >> 8);
i2c_send(data);
i2c_stop();
}

View File

@ -18,6 +18,7 @@ uint8_t i2c_recv();
void i2c_stop(); void i2c_stop();
void i2c_start(uint8_t addr, bool rw); void i2c_start(uint8_t addr, bool rw);
uint8_t i2c_read_reg_addr16(uint8_t device, uint16_t addr); uint8_t i2c_read_reg_addr16(uint8_t device, uint16_t addr);
void i2c_write_reg_addr16(uint8_t device_addr, uint16_t device_reg, uint8_t data);
void i2c_init(); void i2c_init();

View File

@ -7,6 +7,9 @@
#include "ssd1306_display_driver.h" #include "ssd1306_display_driver.h"
#include "debug.h" //TODO move to timer #include "debug.h" //TODO move to timer
#include "br24t_eeprom_driver.h" #include "br24t_eeprom_driver.h"
#include "pcf_clock_driver.h"
#include "pins.h"
#include "uart.h"
/** /**
* TODO * TODO
* make sure desired functions are static (it's just good practice) * make sure desired functions are static (it's just good practice)
@ -19,37 +22,41 @@
*/ */
#if defined(DEBUG_BUILD) || defined(EEPROM_INSTALL)
#include "uart.h" //TODO remove if needed
#endif
int main() { int main() {
LED_DEBUG_DDR |= _BV(LED_DEBUG); //TODO move to debug file or somethin
LED_DEBUG_PORT &= ~(_BV(LED_DEBUG));
//initlizes i2c, right now only speed //TODO don't delegate a whole function if desired //initlizes i2c, right now only speed //TODO don't delegate a whole function if desired
i2c_init(); i2c_init();
screen_init(); //screen_init();
#if defined(DEBUG_BUILD) || defined(EEPROM_INSTALL) #if defined(DEBUG_BUILD) || defined(FLASH_EEPROM)
//initlizes usart registers
uart_init(); uart_init();
FILE stdout_replacement = FDEV_SETUP_STREAM((void *)uart_sendbyte, NULL, _FDEV_SETUP_WRITE); FILE stdout_replacement = FDEV_SETUP_STREAM((void *)uart_sendbyte, NULL, _FDEV_SETUP_WRITE);
FILE stdin_replacement = FDEV_SETUP_STREAM(NULL, (void *)uart_recvbyte, _FDEV_SETUP_READ); FILE stdin_replacement = FDEV_SETUP_STREAM(NULL, (void *)uart_recvbyte, _FDEV_SETUP_READ);
stdout = &stdout_replacement; stdout = &stdout_replacement;
stdin = &stdin_replacement; stdin = &stdin_replacement;
screen_testdraw();
//screen_lowlvl_testdraw();
//eeprom_testbyte();
//test_clock();
#endif #endif
//initilize timer //initilize timer
timer_init(); timer_init();
#ifdef EEPROM_INSTALL #ifdef FLASH_EEPROM
//uart_echo();
flash_eeprom(); flash_eeprom();
#endif #endif
//initlizes screen registers with good values since we dont have control over reset functionallity //initlizes screen registers with good values since we dont have control over reset functionallity
screen_init(); //screen_init();
return 0; return 0;
} }

View File

@ -4,14 +4,16 @@ CC=$(TOOLCHAIN_DIR)/bin/avr-gcc
LD=$(TOOLCHAIN_DIR)/bin/avr-ld LD=$(TOOLCHAIN_DIR)/bin/avr-ld
INC=$(TOOLCHAIN_DIR)/avr/include INC=$(TOOLCHAIN_DIR)/avr/include
OUT=compiled_payload.elf OUT=compiled_payload.elf
DEVICE=atmega2560 #DEVICE=atmega2560
DEVICE=atmega328p
F_CPU=16000000 F_CPU=16000000
DEBUG=1 DEBUG=1
#avrdude options #avrdude options
PARTNO=ATmega2560 #PARTNO=ATmega2560
PORT=/dev/ttyACM1 PARTNO=ATmega328p
PORT=/dev/ttyUSB0
BAUD=115200 BAUD=115200
@ -25,23 +27,31 @@ make:
#$(CC) -mmcu=$(DEVICE) -I $(INC) -c debug_serial.o -DDEBUG_BUILD=$(DEBUG) -DBAUD=$(RUNTIME_BAUDRATE) -DF_CPU=$(F_CPU) -Wall -O1 i2c.c #$(CC) -mmcu=$(DEVICE) -I $(INC) -c debug_serial.o -DDEBUG_BUILD=$(DEBUG) -DBAUD=$(RUNTIME_BAUDRATE) -DF_CPU=$(F_CPU) -Wall -O1 i2c.c
#$(LD) -mavr6 -o $(OUT) -s main.o debug_serial.o #TODO wish I knew how to make -mavr6 dependent on DEVICE #$(LD) -mavr6 -o $(OUT) -s main.o debug_serial.o #TODO wish I knew how to make -mavr6 dependent on DEVICE
#TODO no debug.c if debug disabled #TODO no debug.c if debug disabled
$(CC) -mmcu=$(DEVICE) -I $(INC) -o $(OUT) -DDEBUG_BUILD=$(DEBUG) -DBAUD=$(RUNTIME_BAUDRATE) -DF_CPU=$(F_CPU) -Wall -O1 main.c debug.c i2c.c ssd1306_display_driver.c uart.c br24t_eeprom_driver.c paint.c -Wall $(CC) -mmcu=$(DEVICE) -I $(INC) -o $(OUT) -DDEBUG_BUILD=$(DEBUG) -DBAUD=$(RUNTIME_BAUDRATE) -DF_CPU=$(F_CPU) -Wall -O1 main.c debug.c i2c.c ssd1306_display_driver.c uart.c br24t_eeprom_driver.c paint.c pcf_clock_driver.c -Wall
compiledb make --dry-run > /dev/null compiledb make --dry-run > /dev/null
reset:
doas avrdude -c usbtiny -p $(PARTNO)
eeprom_write:
doas avrdude -c usbtiny -p $(PARTNO)
doas ./write_eeprom.py $(PORT) $(RUNTIME_BAUDRATE)
eeprom: eeprom:
./compile_eeprom.py ./compile_eeprom.py
eeprom_install: eeprom_install:
$(CC) -lc -mmcu=$(DEVICE) -I $(INC) -o $(OUT) -DBAUD=$(RUNTIME_BAUDRATE) -DF_CPU=$(F_CPU) -DEEPROM_INSTALL -Wall -O1 debug.c i2c.c ssd1306_driver.c uart.c main.c -Wall $(CC) -mmcu=$(DEVICE) -I $(INC) -o $(OUT) -DFLASH_EEPROM -DDEBUG_BUILD=$(DEBUG) -DBAUD=$(RUNTIME_BAUDRATE) -DF_CPU=$(F_CPU) -Wall -O1 main.c debug.c i2c.c ssd1306_display_driver.c uart.c br24t_eeprom_driver.c paint.c -Wall
doas avrdude -v -p $(PARTNO) -P $(PORT) -c wiring -b $(BAUD) -D -U flash:w:$(OUT):e doas avrdude -B 1 -v -p $(PARTNO) -c usbtiny -U flash:w:$(OUT):e
doas ./write_eeprom.py $(PORT) $(SPEED)
install: $(OUT) install: $(OUT)
doas avrdude -v -p $(PARTNO) -P $(PORT) -c wiring -b $(BAUD) -D -U flash:w:$(OUT):e doas avrdude -B 1 -v -p $(PARTNO) -c usbtiny -U flash:w:$(OUT):e
#doas avrdude -v -p $(PARTNO) -P $(PORT) -c wiring -b $(BAUD) -D -U flash:w:$(OUT):e
screen: screen:
screen $(PORT) $(RUNTIME_BAUDRATE) doas avrdude -c usbtiny -p $(PARTNO)
doas screen $(PORT) $(RUNTIME_BAUDRATE)
clean: clean:
rm -f *.o *.elf compiled_eeprom rm -f *.o *.elf compiled_eeprom

View File

@ -1,4 +1,6 @@
#include <i2c.h> #include <util/delay.h>
#include <stdio.h>
#include "i2c.h"
#define CLOCK_ADDR 0x51 #define CLOCK_ADDR 0x51
#ifdef FLASH_EEPROM #ifdef FLASH_EEPROM
@ -6,10 +8,5 @@ void flash_clock() {
i2c_write_reg(EEPROM_ADDR, 0x00, 0x58); //resets clock i2c_write_reg(EEPROM_ADDR, 0x00, 0x58); //resets clock
i2c_write_reg(CLOCK_ADDR, 0x00, 0x40); //sets to 12 hour time i2c_write_reg(CLOCK_ADDR, 0x00, 0x40); //sets to 12 hour time
i2c_write_reg(CLOCK_ADDR, 0x01, 0x08); //sets alarm interrupts on i2c_write_reg(CLOCK_ADDR, 0x01, 0x08); //sets alarm interrupts on
//recieve time
} }
i2c_write_reg(CLOCK_ADDR, 0x03, 0x01); //free ram byte; says we've set the time
#endif #endif

View File

@ -4,3 +4,6 @@ void clock_init();
void set_time(time_t time); void set_time(time_t time);
time_t get_time(); time_t get_time();
void set_alarm(time_t time); void set_alarm(time_t time);
//TODO REMOVE ME
void test_clock();

25
src/pins.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef __PINS_INC
/**
* CTS is connected to CTS, CTS is 1 when we are ready
* scope pins:
* 1: desktop tx
* 2: desktop rx
* 3: desktop rts
* 4: desktop cts
*/
#define __PINS_INC
#include <avr/io.h>
#define UART_DDR DDRD
#define UART_CTS PD2 //cyan
#define UART_RTS PD3 //yellow
#define UART_PORT PORTD
#define LED_DEBUG_DDR DDRB
#define LED_DEBUG_PORT PORTB
#define LED_DEBUG PB5
#endif

View File

@ -20,7 +20,7 @@
void screen_init() { void screen_init() {
#ifdef DEBUG_BUILD #ifdef DEBUG_BUILD
printf("initlizing SSD1306 display driver\n"); printf("initlizing SSD1306 display driver\r\n");
#endif #endif
//turn on screen while we configure shit, it might look cooler //turn on screen while we configure shit, it might look cooler
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0xaf); i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0xaf);
@ -86,42 +86,3 @@ void screen_update() {
} }
} }
#ifdef DEBUG_BUILD
//ugly code below
void scroll_test() {
//sets scroll area to whole screen
i2c_write_reg_multi(SSD1306_ADDR, SSD1306_CMD_REG, 3, (uint8_t[]){0xa3, 0x00, 0x20});
//set up scroll options
i2c_write_reg_multi(SSD1306_ADDR, SSD1306_CMD_REG, 6, (uint8_t[]){0x29, 0x00, 0x00, 0x00, 0x04, 0x00});
//actually activate scroll
i2c_write_reg_multi(SSD1306_ADDR, SSD1306_CMD_REG, 6, (uint8_t[]){0x2f});
}
void screen_testdraw() {
unsigned int on_pix;
unsigned int on_page;
printf("running screen time tests\n");
printf("generating test image...\n");
for(on_pix = 0; on_pix < sizeof(screen_buffer); on_pix++)
screen_buffer[on_pix] = ((uint8_t)0xaa << (on_pix % 8));
printf("page mode, individual byte per i2c call...\n");
for(on_page = 0; on_page < SCREEN_PAGE_CNT; on_page++) {
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0xb0 + on_page);
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0x00);
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0x10);
for(on_pix = 0; on_pix < SCREEN_RES_X; on_pix++)
i2c_write_reg(SSD1306_ADDR, SSD1306_DATA_REG, screen_buffer[(on_page * 8) + on_pix]);
}
printf("page mode, 1 page per i2c call...\n");
for(on_page = 0; on_page < SCREEN_PAGE_CNT; on_page++) {
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0xb0 + on_page);
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0x00);
i2c_write_reg(SSD1306_ADDR, SSD1306_CMD_REG, 0x10);
i2c_write_reg_multi(SSD1306_ADDR, SSD1306_DATA_REG, SCREEN_RES_X, &screen_buffer[on_page * SCREEN_RES_X]);
}
}
#endif

View File

@ -1,6 +1,7 @@
#include <avr/io.h> #include <avr/io.h>
#include <stdio.h> #include <stdio.h>
#include <util/setbaud.h> #include <util/setbaud.h>
#include "pins.h"
/** UART notes /** UART notes
* UCSR0A: * UCSR0A:
@ -35,27 +36,36 @@
* ____________________________________________________________ * ____________________________________________________________
* UBRR0(H,L): baudrates * UBRR0(H,L): baudrates
* *
*
**/ **/
//TODO replace with static void and just use high level functions? //TODO replace with static void and just use high level functions?
void uart_sendbyte(uint8_t byte) { void uart_sendbyte(uint8_t byte) {
if(byte == '\n') uart_sendbyte('\r'); UART_PORT &= ~(_BV(UART_RTS)); //us: ready to send
loop_until_bit_is_set(UCSR0A, UDRE0); loop_until_bit_is_clear(UART_PORT, UART_CTS); //them: go ahead
//also wait for buffer to be empty, should never be a problem
loop_until_bit_is_set(UCSR0A, UDRE0); //done recieving
UDR0 = byte; UDR0 = byte;
UART_PORT |= _BV(UART_RTS); //keep in mind cts is inverted; low is 1 and high is 0
} }
//TODO replace with static void and just use high level functions? //TODO replace with static void and just use high level functions?
uint8_t uart_recvbyte() { uint8_t uart_recvbyte() {
loop_until_bit_is_set(UCSR0A, RXC0); loop_until_bit_is_clear(UART_PORT, UART_CTS); //wait for their request
UART_PORT &= ~(_BV(UART_RTS)); //hey, you can send now
loop_until_bit_is_set(UCSR0A, RXC0); //wait for them to actually send
UART_PORT |= _BV(UART_RTS); //okay, you can no longer send
return UDR0; return UDR0;
} }
void uart_init() { void uart_init() {
//set baud rate //set baud rate
UART_DDR |= _BV(UART_RTS);
UART_PORT |= _BV(UART_RTS); //keep in mind cts is inverted; low is 1 and high is 0
UBRR0H = UBRRH_VALUE; UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE; UBRR0L = UBRRL_VALUE;
/** /**
TODO figure out why USE_2X is enable when it shoudn't be TODO figure out why USE_2X is enable when it shoudn't be
//set baud rate //set baud rate

View File

@ -1,3 +1,8 @@
#ifndef __UART_INC
#define __UART_INC
void uart_init(); void uart_init();
void uart_sendbyte(uint8_t byte); void uart_sendbyte(uint8_t byte);
uint8_t uart_recvbyte(); uint8_t uart_recvbyte();
#define HARDWARE_FLOW 1 //TODO
#endif

View File

@ -2,9 +2,11 @@
import serial import serial
import argparse import argparse
import os import os
from time import sleep
from math import ceil
#we send syn, recv ack #we send syn, recv ack
SYN_MAGIC = 0xdeafbeef SYN_MAGIC = 0xdeadbeef
ACK_MAGIC = 0xf00dd00d ACK_MAGIC = 0xf00dd00d
EEPROM_PAGESIZE = 64 EEPROM_PAGESIZE = 64
@ -18,33 +20,57 @@ args = parser.parse_args()
eeprom_file = open("./compiled_eeprom", "rb") eeprom_file = open("./compiled_eeprom", "rb")
eeprom_filesize = os.fstat(eeprom_file.fileno()).st_size eeprom_filesize = os.fstat(eeprom_file.fileno()).st_size
page_len = ceil(eeprom_filesize / EEPROM_PAGESIZE)
s = serial.Serial(args.port, args.baud, timeout = 0) s = serial.Serial(port=args.port, baudrate=args.baud, parity=serial.PARITY_NONE, timeout=0, dsrdtr=1)
s.write(SYN_MAGIC)
def handle_writer_error(): #slow method
def write_hwf(data):
debugval = 0
print("writing")
data_parsed = [data[b:b+1] for b in range(len(data))]
for c in data_parsed:
print(debugval)
debugval += 1
s.rts = 1
while not s.cts:
pass
s.rts = 0
s.write(c)
def read_hwf(length):
print("reading")
msg = b''
for c in range(length):
s.rts = 1
while not s.cts:
pass
s.rts = 0
msg += s.read(size=1)
return(msg)
def handle_writer_error(write_status):
if write_status == 1: # verification failed if write_status == 1: # verification failed
print("Verification failed on page {}!".format(page)) print("Verification failed on page {}!".format(page))
elif write_status == 0xff: elif write_status == 0xff:
print("Unknown error writing page {}!".format(page)) print("Unknown error writing page {}!".format(page))
#while True:
# write_hwf(b"abcdef\r\n")
# print(read_hwf(10))
while not s.read(4) == ACK_MAGIC: write_hwf(page_len.to_bytes(1, 'little'))
pass
print("Device detected, writing eeprom...") for page in range(0, page_len):
for page in range(0, int(eeprom_filesize / EEPROM_PAGESIZE)): print(page)
s.write(eeprom_file.read(EEPROM_PAGESIZE)) if EEPROM_PAGESIZE > (eeprom_filesize - eeprom_file.tell()):
write_status = s.read(1) write_hwf(eeprom_file.read())
[write_hwf(b'\x00') for b in range(0, eeprom_filesize % EEPROM_PAGESIZE)]
else:
write_hwf(eeprom_file.read(EEPROM_PAGESIZE))
write_status = read_hwf(1)
print("WRITE STATUS: {}".format(write_status))
if not write_status == 0: if not write_status == 0:
handle_writer_error(write_status) handle_writer_error(write_status)
if eeprom_file.tell() < eeprom_filesize: print("Done writing to EEPROM!\n")
s.write(eeprom_file.read())
[s.write(0) for b in range(0, eeprom_filesize % EEPROM_PAGESIZE)]
write_status = s.read(1)
if not write_status == 0:
handle_writer_error(write_status)
print("Done writing to EEPROM! You are still alone!")