summaryrefslogtreecommitdiff
path: root/firmware/rf test/Core/Src/sharpmem.c
blob: 0117921676554199043e2adcbb751fa7d018aef9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include "sharpmem.h"
#include "fonts.h"

void SHARPMEM_TOGGLEVCOM(SharpMemDisplay_t *display) {
    display->_sharpmem_vcom = display->_sharpmem_vcom ? 0x00 : SHARPMEM_BIT_VCOM;  
}

void SHARPMEM_draw_pixel(SharpMemDisplay_t *display, uint16_t x, uint16_t y, bool black) {
    if ((x >= display->width) || (y >= display->height))
        return;

    if (black) {
        display->_buffer[(y * display->width + x) / 8] |= (0x1 << (x & 7)); //potentially expensive when run many times, use lookup from adafruit lib
    } else {
        display->_buffer[(y * display->width + x) / 8] &= ~(0x1 << (x & 7));
    }
}

void SHARPMEM_draw_line(SharpMemDisplay_t *display, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool black, uint8_t thickness) {

}

void SHARPMEM_draw_circle(SharpMemDisplay_t *display, uint16_t x, uint16_t y, uint8_t r, bool filled) {

}

void SHARPMEM_draw_rect(SharpMemDisplay_t *display, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, bool filled) {

}

void SHARPMEM_write(SharpMemDisplay_t *display, char *text, uint8_t font_index, uint16_t x0, uint16_t y0, bool inverse, bool force_bg) {
	/*uint8_t mask = 0xFF;
	uint8_t a1, a2, b;
	if(font_index > NUMBER_OF_FONTS) return;
	bitmap_font_t *font = fonts[font_index];

	for (uint8_t ci = 0; ci < strlen(text); ci++){
		uint16_t base_index = font->lookup[(uint8_t)text[ci]];
		uint8_t offset = (x0 + (ci)*font->char_w) % 8;

		for (uint8_t y = 0; y < font->char_h; y++) {
			if(y+y0 > display->height) return;

			uint8_t start_byte = (x0 + ci*font->char_w)/8 + (y0+y)*display->width/8;

			if((x0 + ci*font->char_w % 8))
				memcpy(display->_buffer + ((y+y0)*(display->width)/8) + x0/8 + ci*font->char_w/8 , font->font_bytes + base_index*font->bytes_per_char + y*font->bytes_per_row , font->bytes_per_row);
			else {
				uint8_t charbase = base_index*font->bytes_per_char + y*font->bytes_per_row;
				bool single_ended_last_byte = (offset + font->char_w - 1) / 8 > (bytes_per_row-1);
				uint8_t buffer_bytes = font->bytes_per_row + ( single_ended_last_byte ? 1 : 0 );
				for(uint8_t b_i = 0; b_i < buffer_bytes; b_i++) {
					b = display->_buffer[start_byte + b_i];
					a2 = font->font_bytes[ charbase + b_i ] >> offset;
					if(b_i == 0) {
						b = ((mask >> offset) & a2) + ( (mask << (8-offset)) & b );
					} else if (b_i != (buffer_bytes-1 + !single_ended_last_byte)) {
						a1 = font->font_bytes[ charbase + b_i - 1 ] << (8-offset);
						if (!single_ended_last_byte) {
							uint8_t remainder = (offset + font->char_w) % 8;
							b = ( (a1 + a2) & (mask << (8-remainder)) ) + ((mask >> remainder) & b);
						}
						else b = a1 + a2;
					} else {
						a1 = font->font_bytes[ charbase + b_i - 1 ] << (8-offset);
						uint8_t remainder = (offset + font->char_w) % 8;
						b = ((mask << (8-remainder)) & a1) + ( (mask >> remainder) & b );
					}
					display->_buffer[start_byte + b_i] = b;
				}
				start_byte += font->bytes_per_char;
				end_byte += font->bytes_per_char;
			}
		}
	}*/

	// potentially inefficient but simplest algorithm involving reading and writing every single pixel
	if(font_index > NUMBER_OF_FONTS) return;
	bitmap_font_t *font = fonts[font_index];

	for (uint8_t ci = 0; ci < strlen(text); ci++){
		uint16_t base_index = font->lookup[(uint8_t)text[ci]];

		for (uint16_t y = 0; y < font->char_h; y++) {
			uint16_t charbase = base_index*font->bytes_per_char + y*font->bytes_per_row;
			for (uint16_t x = 0; x < font->char_w; x++) {
				bool white = ( (font->font_bytes[charbase + x/8] & (0x1 << (x%8)) ) == 0 );
				if (!force_bg && white) continue;
				if (inverse) white = !white;
				SHARPMEM_draw_pixel(display, x0+ci*font->char_w+x, y0+y, !white);
			}
		}
	}
}

uint8_t SHARPMEM_get_pixel(SharpMemDisplay_t *display, uint16_t x, uint16_t y) {
	if ((x >= display->width) || (y >= display->height))
	   return 1; //1 = empty

}

void SHARPMEM_clear_display(SharpMemDisplay_t *display) {
	HAL_GPIO_WritePin(display->lcdmode_pin_bank, display->lcdmode_pin, GPIO_PIN_RESET); // set lcdmode pin to low for manual vcom control

	memset(display->_buffer, 0xff, (display->width * display->height) / 8);

    // Send the clear screen command rather than doing a HW refresh (quicker)
    
    uint8_t clear_data[2] = {(uint8_t)(display->_sharpmem_vcom | SHARPMEM_BIT_CLEAR),
                            0x00};
    
    HAL_GPIO_WritePin(display->cs_pin_bank, display->cs_pin, GPIO_PIN_SET);
    HAL_SPI_Transmit(display->spidev, clear_data, 2, 16);
    HAL_GPIO_WritePin(display->cs_pin_bank, display->cs_pin, GPIO_PIN_RESET);

    SHARPMEM_TOGGLEVCOM(display);
    HAL_GPIO_WritePin(display->lcdmode_pin_bank, display->lcdmode_pin, GPIO_PIN_SET); // set lcdmode pin to high for 1Hz external vcom signal
}

void SHARPMEM_refresh_display(SharpMemDisplay_t *display) {
	HAL_GPIO_WritePin(display->lcdmode_pin_bank, display->lcdmode_pin, GPIO_PIN_RESET); // set lcdmode pin to low for manual vcom control
    uint16_t i, currentline;

    //spidev->beginTransaction();
    // Send the write command
    HAL_GPIO_WritePin(display->cs_pin_bank, display->cs_pin, GPIO_PIN_SET);
    uint8_t write_data[1] = {0x00 | SHARPMEM_BIT_WRITECMD};
    HAL_SPI_Transmit(display->spidev, write_data, 1, 100);
    SHARPMEM_TOGGLEVCOM(display);

    uint8_t bytes_per_line = display->width / 8;
    uint16_t totalbytes = (display->width * display->height) / 8;

    for (i = 0; i < totalbytes; i += bytes_per_line) {
        uint8_t line[bytes_per_line + 2];

        // Send address byte
        currentline = ((i + 1) / (display->width / 8)) + 1;
        line[0] = currentline;
        // copy over this line
        memcpy(line + 1, display->_buffer + i, bytes_per_line);
        // Send end of line
        line[bytes_per_line + 1] = 0x00;
        // send it!
        HAL_SPI_Transmit(display->spidev, line, bytes_per_line + 2, 16);
    }

    // Send another trailing 8 bits for the last line
    HAL_SPI_Transmit(display->spidev, (0x00), 1, 100);
    HAL_GPIO_WritePin(display->cs_pin_bank, display->cs_pin, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(display->lcdmode_pin_bank, display->lcdmode_pin, GPIO_PIN_SET); // set lcdmode pin to high for 1Hz external vcom signal
}

void SHARPMEM_clear_display_buffer(SharpMemDisplay_t *display) {
	memset(display->_buffer, 0xff, (display->width * display->height) / 8);
}

uint8_t *SHARPMEM_get_buffer(SharpMemDisplay_t *display) {

}