/*Projeto de Ian Périgo aluno de TSI da UERN e FIC Embarcatech IFRN
https://www.linkedin.com/in/ianperigo/
https://github.com/IanPerigoUERN
https://github.com/IanPerigoVianna
Bibliotecas do SSD1306, ws2818b e código do teste do display retirados do repositório
Oficial BitDogLab: https://github.com/BitDogLab/BitDogLab-C/blob/main/display_oled/display_oled.c
*/
/*166- https://www.ti.com/lit/ds/symlink/sn74hc166.pdf*/
/*https://docs.wokwi.com/pt-BR/parts/wokwi-74hc165*/
/*Datasheet https://www.ti.com/lit/ds/symlink/sn74hc165-ep.pdf?HQS=dis-dk-null-digikeymode-dsf-pf-null-wwe&ts=1748975820690&ref_url=https%253A%252F%252Fwww.ti.com%252Fgeneral%252Fdocs%252Fsuppproductinfo.tsp%253FdistId%253D10%2526gotoUrl%253Dhttps%253A%252F%252Fwww.ti.com%252Flit%252Fgpn%252Fsn74hc165-ep */
#include <stdio.h>
#include "pico/stdlib.h"
#include "ssd1306.h"
#include "hardware/gpio.h"
#define I2C_SDA 14
#define I2C_SCL 15
#define BTN_B_PIN 6
// Define Shift Register pins based on your initial comment
// For a parallel-in serial-out shift register like 74HC165:
// - Load pin (PL on 74HC165) is connected to PICO_LOAD_PIN
// - Clock pin (CP on 74HC165) is connected to PICO_CLK_PIN
// - Serial Data Output (Q7 or QH on 74HC165) is connected to PICO_DATA_IN_PIN
#define PICO_LOAD_PIN 28 // GP28 - Parallel Load (PL)
#define PICO_CLK_PIN 17 // GP17 - Clock (CLK)
#define PICO_DATA_IN_PIN 16 // GP16 - Serial Data Input (Data from Shift Register)
#define NUM_DIP_SWITCHES 8 // We are reading 8 bits from the DIP switch
uint8_t ssd[ssd1306_buffer_length];
struct render_area frame_area = {
start_column : 0,
end_column : ssd1306_width - 1,
start_page : 0,
end_page : ssd1306_n_pages - 1
};
void setup_gpios() {
gpio_init(BTN_B_PIN);
gpio_set_dir(BTN_B_PIN, GPIO_IN);
gpio_pull_up(BTN_B_PIN);
i2c_init(i2c1, ssd1306_i2c_clock * 1000);
gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);
gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);
gpio_pull_up(I2C_SDA);
gpio_pull_up(I2C_SCL);
ssd1306_init();
calculate_render_area_buffer_length(&frame_area);
// Initialize Shift Register control pins
gpio_init(PICO_LOAD_PIN);
gpio_set_dir(PICO_LOAD_PIN, GPIO_OUT);
gpio_put(PICO_LOAD_PIN, 1); // PL is often active low, so keep it high initially
gpio_init(PICO_CLK_PIN);
gpio_set_dir(PICO_CLK_PIN, GPIO_OUT);
gpio_put(PICO_CLK_PIN, 0); // Clock initially low
gpio_init(PICO_DATA_IN_PIN);
gpio_set_dir(PICO_DATA_IN_PIN, GPIO_IN);
// No pull-up/down needed here as it's driven by the shift register
}
// Function to read the state of the DIP switches from the shift register
uint8_t read_dip_switches() {
uint8_t dip_data = 0;
gpio_put(PICO_LOAD_PIN, 0);
sleep_us(5); // Small delay to ensure the load pulse is registered
gpio_put(PICO_CLK_PIN, 1);
sleep_us(2);
gpio_put(PICO_CLK_PIN, 0);
sleep_us(2);
gpio_put(PICO_LOAD_PIN, 1);
sleep_us(5);
for (int i = 0; i < NUM_DIP_SWITCHES; i++) {
// Shift current data one bit to the left to make space for the new bit
dip_data = dip_data << 1;
// Read the current bit from the shift register's serial output
// Ensure clock is low before reading if register changes output on rising edge
gpio_put(PICO_CLK_PIN, 0); // Not strictly necessary if clock cycle starts low
sleep_us(2); // Allow data line to settle
if (gpio_get(PICO_DATA_IN_PIN)) {
dip_data |= 0x01; // Set the LSB if the input is high
}
gpio_put(PICO_CLK_PIN, 1);
sleep_us(2);
gpio_put(PICO_CLK_PIN, 0);
sleep_us(2);
}
return dip_data;
}
int main() {
stdio_init_all();
setup_gpios();
ssd1306_draw_string(ssd, 8, 8, "VALz ");
render_on_display(ssd, &frame_area);
uint8_t previous_dip_state = 0; // To detect changes
while (1) {
uint8_t current_dip_state = read_dip_switches(); // está constantemente lendo
if (gpio_get(BTN_B_PIN) == 0) { // só imprime na tela quando aperto o botão
printf("DIP Switch State: ");
for (int i = 7; i >= 0; i--) { // esse for é pra mostrar o DIP em binário
printf("%d", (current_dip_state >> i) & 1);
}
printf(" Decimal: %d\n", current_dip_state);
char buffer[1];
sprintf(buffer, "%d", current_dip_state);
ssd1306_draw_string(ssd, 48, 8, buffer);
render_on_display(ssd, &frame_area);
previous_dip_state = current_dip_state;
}
sleep_ms(100); // Read DIP switches every 100ms
}
return 0; // Should not be reached
}