Commit 63eaf98a authored by Robey Pointer's avatar Robey Pointer
Browse files

improve the menu to allow hidden items and a bigger font; remove old gfx code

parent fa762376
......@@ -41,6 +41,7 @@
#include "scancodes.h"
#include "controller.h"
#include "hid_report.h"
#include "menu.h"
#include "ux.h"
#include "Keyboard.h"
......@@ -136,29 +137,18 @@ static void remote_check_for_low_battery(void) {
}
}
int oledbrt=0;
void oled_brightness_inc(void) {
oledbrt+=10;
if (oledbrt>=0xff) oledbrt = 0xff;
gfx_contrast(oledbrt);
}
void oled_brightness_dec(void) {
oledbrt-=10;
if (oledbrt<0) oledbrt = 0;
gfx_contrast(oledbrt);
}
int16_t pwmval = 8;
void kbd_brightness_init(void) {
// initial brightness
OCR0A = pwmval;
// initial brightness
OCR0A = pwmval;
// clear/set, WGM1:0 set (Phase correct PWM)
TCCR0A = (1 << 7) | (0 << 6) | (0<<1) | 1;
// clear/set, WGM1:0 set (Phase correct PWM)
TCCR0A = (1 << 7) | (0 << 6) | (0<<1) | 1;
// 3=WGM02, (cs02 2:0 -> clock/256 = 100)
TCCR0B = /*(1 << 3) |*/ (1 << 0) | (0 << 1) | 1;
// 3=WGM02, (cs02 2:0 -> clock/256 = 100)
TCCR0B = /*(1 << 3) |*/ (1 << 0) | (0 << 1) | 1;
}
void kbd_brightness_inc(void) {
......@@ -180,36 +170,6 @@ void kbd_brightness_set(int brite) {
OCR0A = pwmval;
}
void remote_turn_on_som(void) {
gfx_clear();
empty_serial();
term_x = 0;
term_y = 0;
Serial_SendByte('1');
Serial_SendByte('p');
Serial_SendByte('\r');
Delay_MS(1);
empty_serial();
ux_splash();
kbd_brightness_init();
}
void remote_turn_off_som(void) {
ux_unsplash();
empty_serial();
term_x = 0;
term_y = 0;
Serial_SendByte('0');
Serial_SendByte('p');
Serial_SendByte('\r');
Delay_MS(1);
empty_serial();
}
void remote_reset_som(void) {
empty_serial();
......@@ -313,18 +273,21 @@ const MenuItem menu_items[] = {
{ "KBD Power-Off p", KEY_P }
};
#include "menu.h"
const menu_item_t circle_menu[] = {
{ "Exit Menu ESC", KEY_ESCAPE, NULL },
{ "Power On 1", KEY_1, controller_turn_on_som },
{ "Power Off 0", KEY_0, controller_turn_off_som },
{ "Reset R", KEY_R, NULL },
{ "Battery Status B", KEY_B, ux_show_battery },
{ "Key Backlight - F1", KEY_F1, NULL },
{ "Key Backlight + F2", KEY_F2, NULL },
{ "Wake SPC", KEY_SPACE, NULL },
{ "System Status S", KEY_S, ux_show_status },
MENU_END
{ "Exit Menu", "ESC", KEY_ESCAPE, true, NULL },
{ "Power On", "1", KEY_1, true, controller_turn_on_som },
{ "Power Off", "0", KEY_0, true, controller_turn_off_som },
{ "Reset", "R", KEY_R, true, NULL },
{ "Battery Status", "B", KEY_B, true, ux_show_battery },
{ "Key Light -", "F1", KEY_F1, false, ux_decrease_oled_brightness },
{ "Key Light +", "F2", KEY_F2, false, ux_increase_oled_brightness },
{ "Wake", "SPC", KEY_SPACE, true, NULL },
{ "System Status", "S", KEY_S, true, ux_show_status },
MENU_END
};
#endif
......@@ -334,16 +297,6 @@ int active_meta_mode = 0;
int execute_meta_function(int keycode);
void render_menu(int y) {
gfx_clear();
gfx_invert_row(current_menu_y-y);
for (int i=0; i<MENU_NUM_ITEMS; i++) {
gfx_poke_str(0,i-y,menu_items[i].title);
}
gfx_on();
gfx_flush();
}
int execute_menu_function(int y) {
if (y>=0 && y<MENU_NUM_ITEMS) {
return execute_meta_function(menu_items[y].keycode);
......@@ -353,16 +306,7 @@ int execute_menu_function(int y) {
// returns 1 for navigation function (stay in meta mode), 0 for terminal function
int execute_meta_function(int keycode) {
if (keycode == KEY_0) {
// TODO: are you sure?
remote_turn_off_som();
EnterPowerOff();
}
else if (keycode == KEY_1) {
remote_turn_on_som();
return 0;
}
else if (keycode == KEY_R) {
if (keycode == KEY_R) {
// TODO: are you sure?
remote_reset_som();
}
......@@ -375,14 +319,6 @@ int execute_meta_function(int keycode) {
else if (keycode == KEY_V) {
remote_turn_off_aux();
}*/
else if (keycode == KEY_B) {
ux_show_battery();
return 0;
}
else if (keycode == KEY_S) {
ux_show_status();
return 0;
}
else if (keycode == KEY_Z) {
low_battery_alert = !low_battery_alert;
if (!low_battery_alert) {
......@@ -391,42 +327,6 @@ int execute_meta_function(int keycode) {
}
return 0;
}
else if (keycode == KEY_F1) {
kbd_brightness_dec();
return 1;
}
else if (keycode == KEY_F2) {
kbd_brightness_inc();
return 1;
}
else if (keycode == HID_KEYBOARD_SC_UP_ARROW) {
current_menu_y--;
if (current_menu_y<0) current_menu_y = 0;
if (current_menu_y<=current_scroll_y) current_scroll_y--;
if (current_scroll_y<0) current_scroll_y = 0;
render_menu(current_scroll_y);
return 1;
}
else if (keycode == HID_KEYBOARD_SC_DOWN_ARROW) {
current_menu_y++;
if (current_menu_y>=MENU_NUM_ITEMS) current_menu_y = MENU_NUM_ITEMS-1;
if (current_menu_y>=current_scroll_y+3) current_scroll_y++;
render_menu(current_scroll_y);
return 1;
}
else if (keycode == KEY_ENTER) {
return execute_menu_function(current_menu_y);
}
else if (keycode == KEY_ESCAPE) {
gfx_clear();
gfx_flush();
}
else if (keycode == KEY_P) {
EnterPowerOff();
}
gfx_clear();
gfx_flush();
return 0;
}
......@@ -533,14 +433,7 @@ static uint8_t scan_keyboard_enhanced(uint8_t keys[]) {
uint8_t count = scan_keyboard(keys);
if (count == 1 && keys[0] == KEY_CIRCLE && !in_circle_menu && !previous_key) {
#if 0
current_scroll_y = 0;
current_menu_y = 0;
// render menu
render_menu(current_scroll_y);
#else
menu_start(circle_menu);
#endif
in_circle_menu = true;
previous_key = KEY_CIRCLE;
return 0;
......@@ -552,13 +445,8 @@ static uint8_t scan_keyboard_enhanced(uint8_t keys[]) {
if (in_circle_menu) {
if (count == 1 && keys[0] != previous_key) {
#if 0
int stay_in_menu = execute_meta_function(keys[0]);
#else
int stay_in_menu = menu_key(keys[0]);
#endif
in_circle_menu = menu_key(keys[0]);
previous_key = keys[0];
if (!stay_in_menu) in_circle_menu = false;
}
return 0;
}
......@@ -681,8 +569,6 @@ void SetupHardware()
kbd_brightness_init();
oled_init();
display_init(&font_oranj);
gfx_clear();
gfx_flush();
hid_report_init();
ux_splash();
......
......@@ -67,6 +67,7 @@
/* Function Prototypes: */
void SetupHardware(void);
void kbd_brightness_init(void);
void EVENT_USB_Device_Connect(void);
void EVENT_USB_Device_Disconnect(void);
......
......@@ -11,6 +11,9 @@
#include <stdlib.h>
#include "LUFA/Drivers/Peripheral/Serial.h"
#include "controller.h"
#include "display.h"
#include "Keyboard.h"
#include "ux.h"
// how long do we wait (busy loops) before giving up on a response
#define TIMEOUT (500000)
......@@ -95,19 +98,18 @@ void controller_probe_batteries(battery_info_t *info) {
info->total_percent = atoi(bat_gauge);
}
bool controller_turn_on_som(void) {
void controller_turn_on_som(void) {
display_clear();
display_flush();
controller_send("1p");
flush();
ux_splash();
kbd_brightness_init();
return false;
}
bool controller_turn_off_som(void) {
void controller_turn_off_som(void) {
ux_unsplash();
controller_send("0p");
flush();
return false;
EnterPowerOff();
}
......@@ -20,5 +20,5 @@ typedef struct {
void controller_init(void);
const char *controller_request(const char *command);
void controller_probe_batteries(battery_info_t *info);
bool controller_turn_on_som(void);
bool controller_turn_off_som(void);
void controller_turn_on_som(void);
void controller_turn_off_som(void);
......@@ -27,7 +27,6 @@ static uint8_t text_width = 0;
static uint8_t text_cursor = 0;
static bool text_dirty = false;
static bool text_inverting = false;
static uint8_t text_roll = 0; // FIXME hack
void display_init(const monospace_font_t *font) {
text_font = font;
......@@ -43,7 +42,6 @@ void display_clear(void) {
text_cursor = 0;
text_dirty = true;
text_inverting = false;
text_roll = 0;
}
void display_clear_line(uint8_t line) {
......@@ -59,6 +57,10 @@ void display_invert_line(uint8_t line) {
}
}
uint8_t display_text_width(void) {
return text_width;
}
uint8_t display_text_height(void) {
return text_height;
}
......@@ -144,12 +146,6 @@ void display_flush(void) {
int i = 0;
uint8_t cursor = 0;
for (uint8_t y = 0; y < text_height; y++) {
if (y < text_roll) {
// skip row
for (uint8_t x = 0; x < DisplayWidth; x++) oled_render(0);
continue;
}
for (uint8_t row = 0; row < stride; row++) {
// back up if we're drawing the later row of a tall font
if (row > 0) cursor -= text_width;
......@@ -167,17 +163,15 @@ void display_flush(void) {
}
for (uint8_t pad = 0; pad < x_offset; pad++) framebuffer[i++] = 0;
}
if (text_roll == 1 && text_font->height > 8) {
// skip row
for (uint8_t x = 0; x < DisplayWidth; x++) oled_render(0);
}
render();
text_dirty = false;
}
void display_bitmap(const uint8_t *data) {
memmove(framebuffer, data, sizeof(framebuffer));
void display_bitmap(uint16_t offset, const uint8_t *data, uint16_t len) {
uint16_t max_len = sizeof(framebuffer) - offset;
if (len > max_len) len = max_len;
memmove(framebuffer + offset, data, len);
render();
}
......@@ -188,24 +182,49 @@ static void check_effect(int i) {
render();
}
void display_packed_bitmap(const uint8_t *data, bool cursor_effect) {
int i = 0;
while (true) {
uint8_t header = pgm_read_byte(data++);
if (header == 0) break;
static uint8_t data_read_byte(const uint8_t *p) {
return *p;
}
static uint8_t code_read_byte(const uint8_t *p) {
return pgm_read_byte(p);
}
static void _display_packed_bitmap(
uint8_t (*reader)(const uint8_t *p),
uint16_t offset,
const uint8_t *data,
uint16_t len,
bool cursor_effect
) {
int i = offset;
const uint8_t *end = data + len;
while (i < sizeof(framebuffer) && data < end) {
uint8_t header = reader(data++);
if (header == 0 || data >= end) break;
uint8_t n = header & 0x7f;
if (header & 0x80) {
uint8_t repeat = pgm_read_byte(data++);
uint8_t repeat = reader(data++);
for (int j = 0; j < n; j++) {
if (i >= sizeof(framebuffer)) break;
framebuffer[i++] = repeat;
if (cursor_effect) check_effect(i);
}
} else {
for (int j = 0; j < n; j++) {
framebuffer[i++] = pgm_read_byte(data++);
if (i >= sizeof(framebuffer) || data >= end) break;
framebuffer[i++] = reader(data++);
if (cursor_effect) check_effect(i);
}
}
}
render();
}
void display_packed_bitmap(uint16_t offset, const uint8_t *data, uint16_t len) {
_display_packed_bitmap(data_read_byte, offset, data, len, false);
}
void display_packed_bitmap_pgm(uint16_t offset, const uint8_t *data, uint16_t len, bool cursor_effect) {
_display_packed_bitmap(code_read_byte, offset, data, len, cursor_effect);
}
......@@ -32,6 +32,7 @@ void display_init(const monospace_font_t *font);
void display_clear(void);
void display_clear_line(uint8_t line);
void display_invert_line(uint8_t line);
uint8_t display_text_width(void);
uint8_t display_text_height(void);
void display_scroll(void);
void display_putc(uint8_t c);
......@@ -40,4 +41,6 @@ void display_write(const char *text);
void display_move(uint8_t x, uint8_t y);
void display_invert(bool invert);
void display_flush(void);
void display_packed_bitmap(const uint8_t *data, bool cursor_effect);
void display_bitmap(uint16_t offset, const uint8_t *data, uint16_t len);
void display_packed_bitmap(uint16_t offset, const uint8_t *data, uint16_t len);
void display_packed_bitmap_pgm(uint16_t offset, const uint8_t *data, uint16_t len, bool cursor_effect);
......@@ -18,10 +18,20 @@ static uint8_t scroll_top = 0;
static void render(void) {
display_clear();
for (int y = 0; y < display_text_height() && items[scroll_top + y].label != NULL; y++) {
uint8_t row = scroll_top;
for (int y = 0; y < display_text_height(); y++) {
// a blank description is a "hidden" menu item, accessible only via its key
while (items[row].label != NULL && items[row].label[0] == 0) row++;
if (items[row].label == NULL) break; // end of menu
display_move(0, y);
display_write(items[scroll_top + y].label);
if (scroll_top + y == current) display_invert_line(y);
display_write(items[row].label);
if (items[row].key_label != NULL) {
display_move(display_text_width() - strlen(items[row].key_label), y);
display_write(items[row].key_label);
}
if (row == current) display_invert_line(y);
row++;
}
display_flush();
}
......@@ -37,6 +47,10 @@ void menu_stop(void) {
items = NULL;
}
bool menu_is_active(void) {
return items != NULL;
}
static bool menu_action(uint8_t index) {
if (!items[index].action) {
// no action = exit menu
......@@ -46,7 +60,8 @@ static bool menu_action(uint8_t index) {
return false;
}
if (!items[index].action()) {
items[index].action();
if (items[index].terminate_menu) {
// don't clear the screen: might have been a display request
menu_stop();
return false;
......@@ -56,16 +71,22 @@ static bool menu_action(uint8_t index) {
// returns true to stay in menu mode
bool menu_key(uint8_t key) {
uint8_t prev_row = current;
// navigation?
switch (key) {
case HID_KEYBOARD_SC_UP_ARROW:
case KEY_UP_ARROW:
if (current > 0) current--;
if (current < scroll_top) scroll_top--;
while (current > 0 && items[current].label[0] == 0) current--;
if (current == 0 && items[current].label[0] == 0) current = prev_row;
while (current < scroll_top) scroll_top--;
render();
return true;
case HID_KEYBOARD_SC_DOWN_ARROW:
if (items[current + 1].label != NULL) current++;
if (current >= scroll_top + display_text_height()) scroll_top++;
case KEY_DOWN_ARROW:
current++;
while (items[current].label != NULL && items[current].label[0] == 0) current++;
if (items[current].label == NULL) current = prev_row;
while (current >= scroll_top + display_text_height()) scroll_top++;
render();
return true;
case KEY_ENTER:
......
......@@ -10,12 +10,15 @@
#include <stdint.h>
typedef struct {
const char *label;
const char *label; // left side of screen
const char *key_label; // right side of screen
uint8_t keycode;
bool (*action)(void); // return true to stay in menu mode
bool terminate_menu; // if false, we stay in menu mode afterwards
void (*action)(void);
} menu_item_t;
#define MENU_END { NULL, 0, NULL }
#define MENU_END { NULL, NULL, 0, false, NULL }
void menu_start(const menu_item_t *menu);
void menu_stop(void);
bool menu_is_active(void);
bool menu_key(uint8_t key);
......@@ -2,7 +2,6 @@
#include "i2c.h"
#include <string.h>
#include <avr/pgmspace.h>
#include "gfx/font.c"
// in case you want to rotate the screen 180 degrees (half-tau)
#define ROTATE 0
......@@ -105,185 +104,3 @@ void oled_start_render(void) {
void oled_finish_render(void) {
i2c_master_stop();
}
struct CharacterMatrix display;
bool gfx_off(void) {
bool success = false;
//send_cmd1(InvertDisplay);
send_cmd1(DisplayOff);
success = true;
done:
return success;
}
bool gfx_on(void) {
bool success = false;
send_cmd1(NormalDisplay);
send_cmd1(DisplayOn);
success = true;
done:
return success;
}
void gfx_contrast(int c) {
send_cmd2(SetContrast, c);
done:
return;
}
void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c) {
*matrix->cursor = c;
++matrix->cursor;
if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) {
// We went off the end; scroll the display upwards by one line
memmove(&matrix->display[0], &matrix->display[1],
MatrixCols * (MatrixRows - 1));
matrix->cursor = &matrix->display[MatrixRows - 1][0];
memset(matrix->cursor, ' ', MatrixCols);
}
}
void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) {
matrix->dirty = true;
if (c == '\n') {
// Clear to end of line from the cursor and then move to the
// start of the next line
uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols;
while (cursor_col++ < MatrixCols) {
matrix_write_char_inner(matrix, ' ');
}
return;
}
matrix_write_char_inner(matrix, c);
}
void gfx_poke(uint8_t x, uint8_t y, uint8_t c) {
display.display[y][x] = c;
}
void gfx_poke_str(uint8_t x, uint8_t y, char* str) {
int len = strlen(str);
if (len>21) len = 21;
// clip
if (y<0 || y>3) return;
for (int xx=x; xx<x+len && xx<21; xx++) {
if (xx>=0 && xx<21) {
display.display[y][xx] = (uint8_t)str[xx-x];
}
}
}
void gfx_write_char(uint8_t c) {
matrix_write_char(&display, c);
}