powerpic
Replacement board for a Casio CA-53W
/** @file settings.c
*
* This mode provides a way to configure watch settings.
*/
#include <xc.h>
#include "drivers/rtcc.h"
#include "lib/mode.h"
#include "lib/events.h"
#include "lib/tick.h"
#include "lib/display.h"
#include "lib/buttons.h"
#include "lib/keypad.h"
#include "lib/settings.h" // This might get confusing
#include "modes/mode_settings.h" // Oh yea this is gonna be bad
#include "lib/logging.h"
#include "modes/settings.h"
#undef LOG_TAG
#define LOG_TAG "mode.settings"
// Each setting item holds a display label and the setting value.
typedef struct
{
const char * label;
volatile int value;
} settings_item_t;
// This array holds a setting struct for each setting.
// The values defined here are the defaults.
static settings_item_t settings_list[] = {
{"rtc", 0}, // RTC Drift Calibration
// {"max", -128},
// {"min", 127},
};
// Setting index values as enum
enum settings_items {
SETTING_RTC,
// SETTING_MAX,
// SETTING_MIN,
MAX_SETTINGS,
};
// Display setting's label and value
static void settings_display (unsigned char setting_index);
static void settings_display_edit (unsigned char setting_index);
// Set setting
static void settings_value_set (unsigned char setting_index, int value);
// Run function that gets input from user for value.
signed char settings_edit (unsigned int event);
// Holds the current setting index
static unsigned char settings_active = 0;
// Holds the current value being edited
static int edit_value = 0;
void
settings_init (void)
{
// Load persistent settings from EEPROM.
// RTCC Calibration
settings_list[SETTING_RTC].value = (int)((signed char)settings_get(SETTING_RTC_OFFSET));
// It's always going to be in range because of storage limits. However, the
// chance of a crystal needing -128 is unlikely, so since this is also the
// value of unwritten EEPROM we assume the latter.
if (settings_list[SETTING_RTC].value == -128)
{
// Default calibration of 0 - no calibration
settings_list[SETTING_RTC].value = 0;
// Set setting (oh god)
settings_set(SETTING_RTC_OFFSET, 0);
}
}
void
settings_start (void)
{
// Display settings tag.
display_secondary_string(1, "SE");
// We use button events.
tick_disable();
// We use the selection keypad.
keypad_keymap_set(KEYMAP_SELECTION);
// Display initial setting.
settings_display(0);
settings_active = 0;
}
signed char
settings_run (unsigned int event)
{
unsigned char keycode;
switch (EVENT_TYPE(event))
{
case EVENT_TICK:
break;
case KEYPAD_EVENT_PRESS:
keycode = EVENT_DATA(event);
if ('>' == keycode)
{
// Next setting
if (MAX_SETTINGS-1 == settings_active)
{
// Loop to first setting
settings_active = 0;
}
else
{
settings_active++;
}
settings_display(settings_active);
}
if ('<' == keycode)
{
// Previous setting
if (0 == settings_active)
{
// Loop to last setting
settings_active = MAX_SETTINGS-1;
}
else
{
settings_active--;
}
settings_display(settings_active);
}
if ('^' == keycode)
{
// Adjust setting +1
}
if ('v' == keycode)
{
// Adjust setting -1
}
if ('=' == keycode)
{
// Edit selection (keypad input)
edit_value = 0; // Initial number is 0.
settings_display_edit(settings_active);
keypad_keymap_set(KEYMAP_CASIO); // Casio keymap
settings_mode.run = &settings_edit; // Edit run loop gets value.
}
break;
case EVENT_BUTTON:
if (BUTTON_MODE_PRESS == EVENT_DATA(event))
{
return 1;
}
break;
default:
break;
}
return 0;
}
signed char
settings_edit (unsigned int event)
{
unsigned char keypress;
switch (EVENT_TYPE(event))
{
case KEYPAD_EVENT_PRESS:
keypress = EVENT_DATA(event);
if ('0' <= keypress && keypress <= '9')
{
// Keypress is a number
keypress = keypress - 48; // Get int value
edit_value = (edit_value * 10) + keypress; // Add keypress as LSD.
// Display new value.
settings_display_edit(settings_active);
}
if ('.' == keypress)
{
// Period key deletes last digit
edit_value /= 10;
// Display new value
settings_display_edit(settings_active);
}
if ('-' == keypress)
{
// Minus key converts number to negative
if (0 < edit_value)
{
edit_value = -edit_value;
}
settings_display_edit(settings_active);
}
if ('+' == keypress)
{
// Plus key converts number to positive
if (0 > edit_value)
{
edit_value = -edit_value;
}
settings_display_edit(settings_active);
}
break;
case EVENT_BUTTON:
if (EVENT_DATA(event) == BUTTON_MODE_PRESS)
{
// Press of the mode button cancels
settings_display(settings_active); // Display value
keypad_keymap_set(KEYMAP_SELECTION); // Set keymap back
settings_mode.run = &settings_run; // Set run loop back
}
else if (EVENT_DATA(event) == BUTTON_ADJ_PRESS)
{
LOG_DEBUG("Setting value %i", edit_value);
// Adj button sets the value
display_primary_clear(0);
display_primary_string(4, "SET"); // Display Confirmation
settings_value_set(settings_active, edit_value);
}
else if (EVENT_DATA(event) == BUTTON_ADJ_RELEASE)
{
// Adj button up returns to main settings loop
keypad_keymap_set(KEYMAP_SELECTION); // Set keymap back
settings_display(settings_active); // Display set value
settings_mode.run = &settings_run; // Set run loop back
}
break;
default:
break;
}
return 0;
}
static void
settings_display (unsigned char setting_index)
{
// Settings are pretty unique so we might should do something different for
// each one.
settings_item_t *setting = &settings_list[setting_index];
display_primary_clear(0); // Clear display
display_primary_string(1, setting->label); // Display label
display_primary_number(-1, setting->value); // Display value
}
static void
settings_display_edit (unsigned char setting_index)
{
// Display the current edited value
settings_item_t *setting = &settings_list[setting_index];
display_primary_clear(0); // Clear display
display_primary_string(1, setting->label); // Display label
display_primary_number(-1, edit_value); // Display value
}
static void
settings_value_set (unsigned char setting_index, int value)
{
settings_item_t *setting = &settings_list[setting_index];
// Each setting needs to set something specific.
switch (setting_index)
{
case SETTING_RTC:
// This setting modifies the RTCCAL register.
// Acceptable values are -128 to 127. (Limited to -127 to 127)
if (127 < value)
{
// Set to max if value is above range.
value = 127;
}
if (-127 > value)
{
// Set to min value if below range
value = -127;
}
rtcc_drift_set((unsigned char)(signed char)value);
// Set this setting (This is horrible)
settings_set(SETTING_RTC_OFFSET, (unsigned char)(signed char)value);
break;
default:
LOG_DEBUG("Setting %s to %i", setting->label, value);
break;
}
// Save new value.
setting->value = value;
}
// EOF //