#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "ssd1306.h"
#include "font.h" // A fonte precisa estar no mesmo diretório
#include <string.h>
#define I2C_PORT i2c0
#define SSD1306_I2C_ADDR 0x3C
#define SSD1306_WIDTH 128
#define SSD1306_HEIGHT 64
#define SSD1306_BUFFER_SIZE (SSD1306_WIDTH * SSD1306_HEIGHT / 8)
static uint8_t buffer[SSD1306_BUFFER_SIZE];
void ssd1306_send_cmd(uint8_t cmd) {
uint8_t buf[] = {0x00, cmd};
i2c_write_blocking(I2C_PORT, SSD1306_I2C_ADDR, buf, 2, false);
}
void ssd1306_send_data(uint8_t* data, size_t len) {
uint8_t *temp_buf = malloc(len + 1);
temp_buf[0] = 0x40;
memcpy(temp_buf + 1, data, len);
i2c_write_blocking(I2C_PORT, SSD1306_I2C_ADDR, temp_buf, len + 1, false);
free(temp_buf);
}
void ssd1306_init() {
ssd1306_send_cmd(0xAE); // display off
ssd1306_send_cmd(0xD5); // set display clock div
ssd1306_send_cmd(0x80); // suggested ratio
ssd1306_send_cmd(0xA8); // set multiplex
ssd1306_send_cmd(SSD1306_HEIGHT - 1);
ssd1306_send_cmd(0xD3); // set display offset
ssd1306_send_cmd(0x0); // no offset
ssd1306_send_cmd(0x40 | 0x0); // line #0
ssd1306_send_cmd(0x8D); // charge pump
ssd1306_send_cmd(0x14); // enable
ssd1306_send_cmd(0x20); // memory mode
ssd1306_send_cmd(0x00); // 00 horizontal
ssd1306_send_cmd(0xA1); // seg remap
ssd1306_send_cmd(0xC8); // com out scan dir
ssd1306_send_cmd(0xDA); // com pins
ssd1306_send_cmd(0x12);
ssd1306_send_cmd(0x81); // contrast
ssd1306_send_cmd(0xCF);
ssd1306_send_cmd(0xD9); // pre-charge
ssd1306_send_cmd(0xF1);
ssd1306_send_cmd(0xDB); // vcom detect
ssd1306_send_cmd(0x40);
ssd1306_send_cmd(0xA4); // resume
ssd1306_send_cmd(0xA6); // normal display
ssd1306_send_cmd(0x2E); // deactivate scroll
ssd1306_send_cmd(0xAF); // display on
}
void ssd1306_clear() {
memset(buffer, 0, SSD1306_BUFFER_SIZE);
}
void ssd1306_show() {
ssd1306_send_data(buffer, SSD1306_BUFFER_SIZE);
}
void ssd1306_draw_pixel(int x, int y) {
if (x < 0 || x >= SSD1306_WIDTH || y < 0 || y >= SSD1306_HEIGHT) return;
buffer[x + (y / 8) * SSD1306_WIDTH] |= (1 << (y % 8));
}
void ssd1306_draw_char(int x, int y, int scale, char c) {
if (c < 32 || c > 126) c = ' ';
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if ((font[c - 32][i] >> j) & 1) {
for (int k = 0; k < scale; k++) {
for (int l = 0; l < scale; l++) {
ssd1306_draw_pixel(x + i * scale + k, y + j * scale + l);
}
}
}
}
}
}
void ssd1306_draw_string(int x, int y, int scale, char *s) {
for (int i = 0; i < strlen(s); i++) {
ssd1306_draw_char(x + i * 8 * scale, y, scale, s[i]);
}
}