#![no_std]
#![no_main]
use esp_backtrace as _;
use esp_hal::{
clock::ClockControl,
delay::Delay,
gpio::Io,
i2c::I2C,
peripherals::Peripherals,
prelude::*,
systimer::SystemTimer,
timer::TimerGroup,
};
use hmac_sha1::Hash;
use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306};
// Adicione esta importação manual para display
use embedded_graphics::{
mono_font::{ascii::FONT_6X10, MonoTextStyle},
pixelcolor::BinaryColor,
prelude::*,
text::Text,
};
static mut TOTP_KEY: [u8; 20] = *b"12345678901234567890"; // Sua chave aqui
#[entry]
fn main() -> ! {
let peripherals = Peripherals::take();
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let mut delay = Delay::new(&clocks);
// Configuração do display (GPIO21 = SDA, GPIO22 = SCL)
let i2c = I2C::new(
peripherals.I2C0,
io.pins.gpio21,
io.pins.gpio22,
100.kHz(),
&clocks,
);
let interface = I2CDisplayInterface::new(i2c);
let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
.into_buffered_graphics_mode();
display.init().unwrap();
let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On);
loop {
let timestamp = (SystemTimer::now() / 1_000_000) as u64 + 1717020000;
let code = generate_totp(unsafe { &TOTP_KEY }, timestamp);
// Atualizar display
display.clear();
Text::new(
&format!("TOTP: {:06}", code),
Point::new(10, 30),
text_style,
)
.draw(&mut display)
.unwrap();
display.flush().unwrap();
delay.delay_ms(30_000u32);
}
}
fn generate_totp(key: &[u8], timestamp: u64) -> u32 {
let period = 30;
let counter = timestamp / period;
let hmac = Hash::new()
.chain(counter.to_be_bytes())
.finalize();
let offset = (hmac[19] & 0x0F) as usize;
let code_bytes = &hmac[offset..offset + 4];
let code = u32::from_be_bytes(code_bytes.try_into().unwrap()) & 0x7FFFFFFF;
code % 1_000_000
}