268 lines
5.3 KiB
C
268 lines
5.3 KiB
C
#include <avr/interrupt.h>
|
|
#include <avr/io.h>
|
|
#include <string.h>
|
|
#include <util/delay.h>
|
|
#include "spi_master.h"
|
|
#include "func.h"
|
|
#include <stdlib.h>
|
|
|
|
#define MAX_DIGITS 12
|
|
#define F_CPU 16000000UL
|
|
#define DELAY_MS 2000
|
|
|
|
void output_on_display(struct calculator *calc)
|
|
{
|
|
char buffer[32];
|
|
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);
|
|
|
|
transmit_num(calc->num1, buffer);
|
|
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);
|
|
|
|
transmit_num(calc->num1, buffer);
|
|
|
|
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);
|
|
|
|
transmit_num(calc->num2, buffer);
|
|
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);
|
|
|
|
transmit_num(calc->num1, buffer);
|
|
|
|
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);
|
|
|
|
transmit_num(calc->num2, buffer);
|
|
|
|
// ðåçóëüòàò
|
|
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);
|
|
|
|
transmit_num(calc->result, buffer);
|
|
|
|
break;
|
|
}
|
|
default:
|
|
display_all_clear(0, buffer);
|
|
}
|
|
}
|
|
|
|
void transmit_num(long number, char *buffer) {
|
|
char number_buffer[MAX_DIGITS];
|
|
char mapped_digits[MAX_DIGITS];
|
|
ltoa(number, number_buffer, 10);
|
|
map_digits(mapped_digits, number_buffer, strlen(number_buffer));
|
|
size_t b_size = display_add_simbol(mapped_digits, strlen(number_buffer), buffer);
|
|
SPI_MasterTransmit(buffer, b_size);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|