#include #include #include #include #include "spi_master.h" #include "func.h" #define MAX_DIGITS 11 #define F_CPU 16000000UL #define DELAY_MS 2000 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; }