Skip to content

Commit 0812878

Browse files
committed
finalise basic functionality
Signed-off-by: Devnol <[email protected]>
1 parent 5e9f6f2 commit 0812878

File tree

4 files changed

+173
-13
lines changed

4 files changed

+173
-13
lines changed

CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ pico_sdk_init()
1515
add_subdirectory(TOTP-MCU)
1616

1717
add_executable(main
18-
main.c
18+
main.c
19+
lcd.c
1920
)
2021

2122
# Pull in our pico_stdlib which aggregates commonly used features
22-
target_link_libraries(main pico_stdlib hardware_rtc TOTP-MCU)
23+
target_link_libraries(main pico_stdlib hardware_rtc hardware_i2c TOTP-MCU)
2324

2425
# enable usb output, disable uart output
2526
pico_enable_stdio_usb(main 1)

lcd.c

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
static int addr = 0x3f; //port i2c port in which the LCD adapter is mapped to. For more info check out pico-examples/i2c/bus_scan
2+
3+
//----------- DO NOT EDIT BELOW THIS LINE (unless you know what you're doing) ------------
4+
//Code from https://github.com/raspberrypi/pico-examples i2c/lcd_1602_i2c.c
5+
6+
#include "pico/stdlib.h"
7+
#include "hardware/i2c.h"
8+
// commands
9+
const int LCD_CLEARDISPLAY = 0x01;
10+
const int LCD_RETURNHOME = 0x02;
11+
const int LCD_ENTRYMODESET = 0x04;
12+
const int LCD_DISPLAYCONTROL = 0x08;
13+
const int LCD_CURSORSHIFT = 0x10;
14+
const int LCD_FUNCTIONSET = 0x20;
15+
const int LCD_SETCGRAMADDR = 0x40;
16+
const int LCD_SETDDRAMADDR = 0x80;
17+
18+
// flags for display entry mode
19+
const int LCD_ENTRYSHIFTINCREMENT = 0x01;
20+
const int LCD_ENTRYLEFT = 0x02;
21+
22+
// flags for display and cursor control
23+
const int LCD_BLINKON = 0x01;
24+
const int LCD_CURSORON = 0x02;
25+
const int LCD_DISPLAYON = 0x04;
26+
27+
// flags for display and cursor shift
28+
const int LCD_MOVERIGHT = 0x04;
29+
const int LCD_DISPLAYMOVE = 0x08;
30+
31+
// flags for function set
32+
const int LCD_5x10DOTS = 0x04;
33+
const int LCD_2LINE = 0x08;
34+
const int LCD_8BITMODE = 0x10;
35+
36+
// flag for backlight control
37+
const int LCD_BACKLIGHT = 0x08;
38+
39+
const int LCD_ENABLE_BIT = 0x04;
40+
41+
// Modes for lcd_send_byte
42+
#define LCD_CHARACTER 1
43+
#define LCD_COMMAND 0
44+
45+
/* Quick helper function for single byte transfers */
46+
void i2c_write_byte(uint8_t val) {
47+
#ifdef i2c_default
48+
i2c_write_blocking(i2c_default, addr, &val, 1, false);
49+
#endif
50+
}
51+
52+
void lcd_toggle_enable(uint8_t val) {
53+
// Toggle enable pin on LCD display
54+
// We cannot do this too quickly or things don't work
55+
#define DELAY_US 600
56+
sleep_us(DELAY_US);
57+
i2c_write_byte(val | LCD_ENABLE_BIT);
58+
sleep_us(DELAY_US);
59+
i2c_write_byte(val & ~LCD_ENABLE_BIT);
60+
sleep_us(DELAY_US);
61+
}
62+
63+
// The display is sent a byte as two separate nibble transfers
64+
void lcd_send_byte(uint8_t val, int mode) {
65+
uint8_t high = mode | (val & 0xF0) | LCD_BACKLIGHT;
66+
uint8_t low = mode | ((val << 4) & 0xF0) | LCD_BACKLIGHT;
67+
68+
i2c_write_byte(high);
69+
lcd_toggle_enable(high);
70+
i2c_write_byte(low);
71+
lcd_toggle_enable(low);
72+
}
73+
74+
void lcd_clear(void) {
75+
lcd_send_byte(LCD_CLEARDISPLAY, LCD_COMMAND);
76+
}
77+
78+
79+
// go to location on LCD
80+
void lcd_set_cursor(int line, int position) {
81+
int val = (line == 0) ? 0x80 + position : 0xC0 + position;
82+
lcd_send_byte(val, LCD_COMMAND);
83+
}
84+
85+
static void inline lcd_char(char val) {
86+
lcd_send_byte(val, LCD_CHARACTER);
87+
}
88+
89+
void lcd_string(const char *s) {
90+
while (*s) {
91+
lcd_char(*s++);
92+
}
93+
}
94+
95+
//carriage return + clear of line
96+
void lcd_cr(int line, int line_length) {
97+
lcd_set_cursor(line, 0);
98+
for (size_t i = 0; i < line_length; i++) lcd_char(0x20); //fill line with whitespaces
99+
lcd_set_cursor(line, 0);
100+
101+
}
102+
103+
void lcd_init() {
104+
lcd_send_byte(0x03, LCD_COMMAND);
105+
lcd_send_byte(0x03, LCD_COMMAND);
106+
lcd_send_byte(0x03, LCD_COMMAND);
107+
lcd_send_byte(0x02, LCD_COMMAND);
108+
109+
lcd_send_byte(LCD_ENTRYMODESET | LCD_ENTRYLEFT, LCD_COMMAND);
110+
lcd_send_byte(LCD_FUNCTIONSET | LCD_2LINE, LCD_COMMAND);
111+
lcd_send_byte(LCD_DISPLAYCONTROL | LCD_DISPLAYON, LCD_COMMAND);
112+
lcd_clear();
113+
}

lcd.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <inttypes.h>
2+
3+
void i2c_write_byte(uint8_t val);
4+
void lcd_toggle_enable(uint8_t val);
5+
void lcd_send_byte(uint8_t val, int mode);
6+
void lcd_clear(void);
7+
void lcd_cr(int line, int line_length);
8+
void lcd_set_cursor(int line, int position);
9+
static void inline lcd_char(char val);
10+
void lcd_string(const char *s);
11+
void lcd_init();

main.c

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,64 @@
11
#include <stdio.h>
22
#include <time.h>
3+
#include <string.h>
34
#include "token.h"
5+
#include "lcd.h"
46
#include "TOTP-MCU/TOTP.h"
57
#include "pico/stdlib.h"
68
#include "pico/util/datetime.h"
79
#include "hardware/gpio.h"
10+
#include "hardware/i2c.h"
811
#include "hardware/rtc.h"
912

1013
//----------- DO NOT EDIT ABOVE THIS LINE (unless you know what you're doing)
1114

1215
#define BUTTON_L_PIN 15 // GPIO number for left button
1316
#define BUTTON_SEL_PIN 14 //GPIO number for select button
1417
#define BUTTON_R_PIN 13 //GPIO number for right button
18+
#define MAX_LINES 2 //Rows of LCD
19+
#define MAX_CHARS 16 //Columns of LCD
1520
#define TZ_OFFSET 3 //time zone offset, modify to your needs
16-
#define OTP_INTERVAL 30 //interval between new codes in seconds, usually 30
1721

1822
//----------- DO NOT EDIT BELOW THIS LINE (unless you know what you're doing) ------------
1923

24+
char lcd_content[MAX_CHARS]; //variable for holding LCD text to be printed
25+
2026
int get_number(int min, int def, int max, char label[6]){ //used to ask for time settings on startup
2127
int curr_num = def;
22-
printf("\n");
28+
lcd_clear();
29+
lcd_set_cursor(0,0);
30+
sprintf(lcd_content, "%s:", label);
31+
lcd_string(lcd_content);
32+
lcd_set_cursor(1,0);
33+
sprintf(lcd_content, "%d", curr_num);
34+
lcd_string(lcd_content);
2335
while (gpio_get(BUTTON_SEL_PIN) == 1) { //inverted because it's pulled up internally
24-
printf("\r");
25-
printf("%s: %d", label, curr_num);
2636
if (gpio_get(BUTTON_L_PIN) == 0) curr_num--; //inverted because it's pulled up internally
2737
else if (gpio_get(BUTTON_R_PIN) == 0) curr_num++; //inverted because it's pulled up internally
28-
2938
if (curr_num < min) curr_num = max;
30-
if (curr_num > max) curr_num = min;
39+
if (curr_num > max) curr_num = min;
40+
41+
if ((gpio_get(BUTTON_L_PIN) == 0) || (gpio_get(BUTTON_R_PIN) == 0)) {
42+
lcd_cr(1, MAX_CHARS);
43+
sprintf(lcd_content, "%d", curr_num);
44+
lcd_string(lcd_content);
45+
}
46+
3147
sleep_ms(150);
3248
} return curr_num;
3349
}
3450

3551
int main() {
52+
//init IO
53+
3654
stdio_init_all();
37-
//init buttons
55+
i2c_init(i2c_default, 100 * 1000);
56+
//use pins 4 and 5 for SDA and SCL
57+
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
58+
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
59+
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
60+
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
61+
3862
gpio_init(BUTTON_L_PIN);
3963
gpio_init(BUTTON_R_PIN);
4064
gpio_init(BUTTON_SEL_PIN);
@@ -45,7 +69,15 @@ int main() {
4569
gpio_set_dir(BUTTON_R_PIN, GPIO_IN);
4670
gpio_set_dir(BUTTON_SEL_PIN, GPIO_IN);
4771

48-
////obtain date and time
72+
lcd_init();
73+
lcd_set_cursor(0, 0);
74+
lcd_string("TOTP Token");
75+
lcd_set_cursor(1,0);
76+
lcd_string("By Devnol");
77+
sleep_ms(1000);
78+
79+
80+
//obtain date and time
4981

5082
int year = get_number(0, 2021, 4095, "Year");
5183
sleep_ms(400);
@@ -104,7 +136,8 @@ int main() {
104136

105137
//instantiate TOTP library
106138
TOTP(hmacKey, HMAC_KEY_LENGTH, OTP_INTERVAL);
107-
139+
lcd_clear();
140+
lcd_set_cursor(0,0);
108141
//main Token generation loop
109142
while (true) {
110143
rtc_get_datetime(&t);
@@ -114,8 +147,10 @@ int main() {
114147
}
115148
strptime(datetime_str, "%A %d %b %H:%M:%S %Y", &tm);
116149
uint32_t newCode = getCodeFromTimestamp(epoch);
117-
printf("Token: %d\n", newCode);
118-
sleep_ms(1000);
150+
lcd_cr(0, MAX_CHARS);
151+
sprintf(lcd_content, "Token: %d", newCode);
152+
lcd_string(lcd_content);
153+
sleep_ms(5000);
119154
}
120155
return 0;
121156
}

0 commit comments

Comments
 (0)