diff --git a/spi_master.c b/spi_master.c new file mode 100644 index 0000000..ea220b7 --- /dev/null +++ b/spi_master.c @@ -0,0 +1,285 @@ +#include +#include +#include +#include +#include "spi_master.h" +#include "func.h" + +#define MAX_DIGITS 11 +#define F_CPU 16000000UL +#define DELAY_MS 3000 + +void output_on_display(struct calculator *calc) +{ + char buffer[8]; + switch (calc->state) + { + case NUMBER_FIRST: + { + size_t b_size = display_all_clear(0, buffer); + SPI_MasterTransmit(buffer, b_size); + + b_size = display_set_page(0x01, buffer); + SPI_MasterTransmit(buffer, b_size); + + int size = count_digits(calc->num1); + char mapped_digits[size]; + prepare_data(mapped_digits, calc->num1, size); + b_size = display_add_simbol(mapped_digits, size, buffer); + SPI_MasterTransmit(buffer, b_size); + + break; + } + case NUMBER_SECOND: + { + size_t b_size = display_all_clear(0, buffer); + SPI_MasterTransmit(buffer, b_size); + + b_size = display_set_page(0x01, buffer); + SPI_MasterTransmit(buffer, b_size); + + int size = count_digits(calc->num1); + char mapped_digits[size]; + prepare_data(mapped_digits, calc->num1, size); + b_size = display_add_simbol(mapped_digits, size, buffer); + SPI_MasterTransmit(buffer, b_size); + + char symbol[] = {0x01}; + // операция + switch (calc->operation) + { + case NO_OP: + break; + case ADD: + symbol[0] = 0x04; + break; + case SUB: + symbol[0] = 0x06; + break; + case DIV: + symbol[0] = 0x08; + break; + case MUL: + symbol[0] = 0x03; + break; + } + + b_size = display_add_simbol(symbol, 1, buffer); + SPI_MasterTransmit(buffer, b_size); + + b_size = display_set_page(0x02, buffer); + SPI_MasterTransmit(buffer, b_size); + + size = count_digits(calc->num2); + char mapped_digits1[size]; + prepare_data(mapped_digits1, calc->num2, size); + b_size = display_add_simbol(mapped_digits1, size, buffer); + SPI_MasterTransmit(buffer, b_size); + break; + } + case RESULT: + { + size_t b_size = display_all_clear(0, buffer); + SPI_MasterTransmit(buffer, b_size); + + b_size = display_set_page(0x01, buffer); + SPI_MasterTransmit(buffer, b_size); + + int size = count_digits(calc->num1); + char mapped_digits[size]; + prepare_data(mapped_digits, calc->num1, size); + b_size = display_add_simbol(mapped_digits, size, buffer); + SPI_MasterTransmit(buffer, b_size); + + char symbol[] = {0x01}; + // операция + switch (calc->operation) + { + case NO_OP: + break; + case ADD: + symbol[0] = 0x04; + break; + case SUB: + symbol[0] = 0x06; + break; + case DIV: + symbol[0] = 0x08; + break; + case MUL: + symbol[0] = 0x03; + break; + } + + b_size = display_add_simbol(symbol, 1, buffer); + SPI_MasterTransmit(buffer, b_size); + + b_size = display_set_page(0x02, buffer); + SPI_MasterTransmit(buffer, b_size); + + size = count_digits(calc->num2); + char mapped_digits1[size]; + prepare_data(mapped_digits1, calc->num2, size); + b_size = display_add_simbol(mapped_digits1, size, buffer); + SPI_MasterTransmit(buffer, b_size); + + // линия + + + // результат + b_size = display_set_page(0x03, buffer); + SPI_MasterTransmit(buffer, b_size); + + symbol[0] = 0x15; + b_size = display_add_simbol(symbol, 1, buffer); + SPI_MasterTransmit(buffer, b_size); + + size = count_digits(calc->result); + char mapped_digits2[size]; + prepare_data(mapped_digits2, calc->result, size); + b_size = display_add_simbol(mapped_digits2, size, buffer); + SPI_MasterTransmit(buffer, b_size); + + break; + } + default: + display_all_clear(0, buffer); + } +} + +void SPI_MasterInit(void) +{ + /* Настройка MOSI и SCK как выход, + все остальные сигналы как вход: */ + SPI_DDRX = (1 << SPI_MOSI) | (1 << SPI_SCK) | (1 << SPI_SS) | (0 << SPI_MISO); + + /* Разрешить работу SPI, режим Master, + установить скорость тактов fck/16: */ + SPCR = (1 << SPE) | (1 << MSTR) | (0 << CPOL) | (0 << CPHA) | (1 << SPR1); + + SPI_PORTX |= (1 << SPI_SS); +} + +void SPI_MasterTransmit(char *buffer, size_t length) +{ + SPI_PORTX &= ~(1 << SPI_SS); + for (int i = 0; i < length; i++) + { + SPDR = buffer[i]; + while (!(SPSR & (1 << SPIF))) + { + // ожидание завершения передачи + } + } + SPI_PORTX |= (1 << SPI_SS); + _delay_ms(DELAY_MS); +} + +char crc8(char *data, int len) { + char crc = 0x00; + while (len--) { + crc ^= *data++; + for (int i = 0; i < 8; i++) { + if (crc & 0x80) { + crc = (crc << 1) ^ 0x07; + } else { + crc <<= 1; + } + } + } + return crc; +} + +//очищение экранa +size_t display_all_clear(char color, char *buffer) +{ + buffer[0] = 0x01; + buffer[1] = color; + buffer[2] = crc8(buffer, 2); + return 3; +} + +//выбор точки +size_t display_set_page(char point, char *buffer) +{ + buffer[0] = 0x02; + buffer[1] = point; + buffer[2] = crc8(buffer, 2); + return 3; +} + +//добавление нового символа и его параметров +size_t display_add_simbol(char *str, size_t str_len, char *buffer) +{ + size_t idx = 0; + buffer[idx] = 0x03; + idx++; + for (int i = 0; i < str_len; i++) + { + buffer[idx] = str[i]; + idx++; + } + buffer[idx] = crc8(buffer, idx); + idx++; + return idx; +} + +//удаление символа и его параметров +size_t display_del_simbol(char number, char *buffer) +{ + buffer[0] = 0x04; + buffer[1] = number; + buffer[2] = crc8(buffer, 2); + return 3; +} + +//закрашивание пикселя +size_t display_draw_pixel(char x, char y, char color, uint8_t *buffer) +{ + buffer[0] = 0x05; + buffer[1] = x; + buffer[2] = y; + buffer[3] = color; + buffer[4] = crc8(buffer, 4); + return 5; +} + +//рисует линию +size_t display_draw_line(char x1, char y1, char x2, char y2, char color, char *buffer) +{ + buffer[0] = 0x06; + buffer[1] = x1; + buffer[2] = y1; + buffer[3] = x2; + buffer[4] = y2; + buffer[5] = color; + buffer[6] = crc8(buffer, 6); + return 7; +} + +//рисует круг +size_t display_draw_circle(char x, char y, char r, char color, uint8_t *buffer) +{ + buffer[0] = 0x07; + buffer[1] = x; + buffer[2] = y; + buffer[3] = r; + buffer[4] = color; + buffer[5] = crc8(buffer, 5); + return 6; +} + +//рисует прямоугольник +size_t display_draw_rectangle(char x, char y, char height, char width, char color, uint8_t *buffer) +{ + buffer[0] = 0x08; + buffer[1] = x; + buffer[2] = y; + buffer[3] = height; + buffer[4] = width; + buffer[5] = color; + buffer[6] = crc8(buffer, 6); + return 7; +} + + diff --git a/spi_master.h b/spi_master.h new file mode 100644 index 0000000..3826c9b --- /dev/null +++ b/spi_master.h @@ -0,0 +1,20 @@ +#define SPI_PORTX PORTB +#define SPI_DDRX DDRB +#define SPI_MISO 4 +#define SPI_MOSI 3 +#define SPI_SCK 5 +#define SPI_SS 2 + +#include "calculator.h" + +void output_on_display(struct calculator *calc); +void SPI_MasterInit(void); +void SPI_MasterTransmit(char *buffer, size_t length); +void transmit_first_num(struct calculator *calc, char *buffer); +void transmit_second_num(struct calculator *calc, char *buffer); +void transmit_result(struct calculator *calc, char *buffer, char *symblo); +size_t display_all_clear(char color, char *buffer); +size_t display_add_simbol(char *str, size_t str_len, char *buffer); +size_t display_draw_line(char x1, char y1, char x2, char y2, char color, char *buffer); +size_t display_del_simbol(char number, char *buffer); +size_t display_set_page(char point, char *buffer);