Skip to content

Commit

Permalink
All options implemented
Browse files Browse the repository at this point in the history
EEPROM saving implemented
Record mode signal inversion added
  • Loading branch information
sweetlilmre committed Aug 22, 2014
1 parent 136dcda commit 3b4b88b
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 44 deletions.
5 changes: 3 additions & 2 deletions comms.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <avr/io.h>
#include <inttypes.h>
#include "tapuino.h"
#include "config.h"
#include "comms.h"

Expand Down Expand Up @@ -99,9 +100,9 @@ void input_callback()
key_press |= key_state & i; // 0->1: key press detect

if( (key_state & REPEAT_MASK) == 0 ) // check repeat function
rpt = (KEY_REPEAT_START / 10); // start delay
rpt = (KEY_REPEAT_START / 10); // start delay
if( --rpt == 0 ){
rpt = (KEY_REPEAT_NEXT / 10); // repeat delay
rpt = g_key_repeat_next; // repeat delay
key_rpt |= key_state & REPEAT_MASK;
}
player_handleInputKeys();
Expand Down
4 changes: 2 additions & 2 deletions config.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
#define LCD_NUM_LINES 2 // number of display lines on the LCD
#define MAX_LCD_LINE_LEN 16 // max number of characters on a line

// Timing constants
#define SPINNER_RATE 250 // milliseconds, granularity 10ms
// Timing constant defaults, these will only apply until eeprom values are saved
#define TICKER_RATE 250 // milliseconds, granularity 10ms
#define TICKER_HOLD 1250 // milliseconds, ticker begin and end hold time, granularity 10ms
#define KEY_REPEAT_START 500 // milliseconds, granularity 10ms
#define KEY_REPEAT_NEXT 300 // milliseconds, granularity 10ms
Expand Down
39 changes: 20 additions & 19 deletions lcdutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <stdio.h>
#include <string.h>
#include <util/delay.h>
#include "tapuino.h"
#include "ff.h"
#include "config.h"
#include "lcd.h"
Expand All @@ -12,8 +13,9 @@
#define DIRECTORY_INDICATOR 0b01111110

char g_char_buffer[MAX_LCD_LINE_LEN + 1] = {0};
uint8_t g_ticker_enabled = 0;

static uint8_t g_ticker_enabled = 0;
static uint8_t g_ticker_index = 0;
static uint32_t g_last_tick = 0;

uint8_t backslashChar[8] = {
0b00000,
Expand All @@ -27,42 +29,41 @@ uint8_t backslashChar[8] = {
};

void filename_ticker(FILINFO* pfile_info, uint32_t cur_tick) {
static uint32_t last_tick = 0;

static uint32_t last_hold = 0;
static uint8_t ticker_index = 0;
char* ticker_string;

if (g_ticker_enabled) {
if (!last_tick) last_tick = cur_tick;
if (!g_last_tick) g_last_tick = cur_tick;

// how often do we tick?
if (cur_tick - last_tick < (SPINNER_RATE / 10)) {
if (cur_tick - g_last_tick < (uint32_t) g_ticker_rate) {
return;
}
last_tick = cur_tick;
g_last_tick = cur_tick;

if (!last_hold) last_hold = cur_tick;
// how long do we hold?
if (cur_tick - last_hold < (TICKER_HOLD / 10)) {
if (cur_tick - last_hold < (uint32_t) g_ticker_hold) {
return;
}

ticker_string = pfile_info->lfname[0] ? pfile_info->lfname : pfile_info->fname;
// is the filename within screen bounds?
if ((strlen(ticker_string) - ticker_index) <= MAX_LCD_LINE_LEN) {
if ((strlen(ticker_string) - g_ticker_index) <= MAX_LCD_LINE_LEN) {
// how long do we hold at the end?
if (cur_tick - last_hold < (TICKER_HOLD * 2 / 10)) {
if (cur_tick - last_hold < (uint32_t) (g_ticker_hold << 1)) {
return;
}
ticker_index = 0;
last_tick = last_hold = 0;
g_ticker_index = 0;
g_last_tick = last_hold = 0;
} else {
//reset to avoid overflow
last_hold = cur_tick - (TICKER_HOLD / 10) - 1;
ticker_index++;
last_hold = cur_tick - g_ticker_hold - 1;
g_ticker_index++;
}

lcd_status(&ticker_string[ticker_index]);
lcd_status(&ticker_string[g_ticker_index]);
if (pfile_info->fattrib & AM_DIR) {
lcd_show_dir();
}
Expand All @@ -78,17 +79,17 @@ void display_filename(FILINFO* pfile_info) {
lcd_show_dir();
}
g_ticker_enabled = strlen(ticker_string) > (MAX_LCD_LINE_LEN - 1);
g_ticker_index = 0;
}

void lcd_spinner_internal(uint32_t cur_tick, int8_t perc, uint16_t rate) {
static uint8_t indicators[] = {'|', '/', '-', 1};
static uint8_t pos = 0;
static uint32_t last_tick = 0;
if (cur_tick - last_tick < (rate / 10)) {
if (cur_tick - g_last_tick < rate) {
return;
}

last_tick = cur_tick;
g_last_tick = cur_tick;
lcd_setCursor(MAX_LCD_LINE_LEN - 7, 0);
if (perc < 0) {
strncpy_P(g_char_buffer, S_MAX_BLANK_LINE, 7);
Expand All @@ -106,7 +107,7 @@ void lcd_spinner_internal(uint32_t cur_tick, int8_t perc, uint16_t rate) {
}

void lcd_spinner(uint32_t cur_tick, int8_t perc) {
lcd_spinner_internal(cur_tick, perc, SPINNER_RATE);
lcd_spinner_internal(cur_tick, perc, g_ticker_rate);
}

void lcd_busy_spinner() {
Expand Down
9 changes: 5 additions & 4 deletions memstrings.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ prog_char S_RECORDING[] PROGMEM = "Recording";
prog_char S_SELECT_RECORD_MODE[] PROGMEM = "Name mode:";
prog_char S_REC_MODE_MANUAL[] PROGMEM = "Manual";
prog_char S_REC_MODE_AUTO[] PROGMEM = "Auto";
prog_char S_ENTER_FILENAME[] PROGMEM = "Enter file name";
prog_char S_ENTER_FILENAME[] PROGMEM = "Enter name";
prog_char S_FILENAME_CHARS[] PROGMEM = " abcdefghijklmnopqrstuvwxyz0123456789_-";

prog_char S_INITI2COK[] PROGMEM = "I2C OK";
prog_char S_INIT[] PROGMEM = "Init...";
prog_char S_INIT_FAILED[] PROGMEM = "Init failed!";
prog_char S_INIT_OK[] PROGMEM = "Init OK.";
Expand All @@ -25,8 +24,10 @@ prog_char S_PRESS_START[] PROGMEM = "Press START";

prog_char S_MODE_OPTIONS[] PROGMEM = "Options";
prog_char S_OPTION_SIGNAL[] PROGMEM = "Invert";
prog_char S_OPTION_KEYS[] PROGMEM = "Keys";
prog_char S_OPTION_DISPLAY[] PROGMEM = "Display";
prog_char S_OPTION_KEY_REPEAT[] PROGMEM = "Key speed";
prog_char S_OPTION_TICKER_SPEED[] PROGMEM = "Ticker speed";
prog_char S_OPTION_TICKER_HOLD[] PROGMEM = "Ticker hold";
prog_char S_OPTION_REC_FINALIZE[] PROGMEM = "Record finalize";

prog_char S_MKDIR_FAILED[] PROGMEM = "MKDIR fail!";
prog_char S_CHDIR_FAILED[] PROGMEM = "CHDIR fail!";
Expand Down
6 changes: 4 additions & 2 deletions memstrings.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ extern prog_char S_PRESS_START[];

extern prog_char S_MODE_OPTIONS[];
extern prog_char S_OPTION_SIGNAL[];
extern prog_char S_OPTION_KEYS[];
extern prog_char S_OPTION_DISPLAY[];
extern prog_char S_OPTION_KEY_REPEAT[];
extern prog_char S_OPTION_TICKER_SPEED[];
extern prog_char S_OPTION_TICKER_HOLD[];
extern prog_char S_OPTION_REC_FINALIZE[];

extern prog_char S_MKDIR_FAILED[];
extern prog_char S_CHDIR_FAILED[];
Expand Down
51 changes: 43 additions & 8 deletions menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
#define REC_MODE_MANUAL 0
#define REC_MODE_AUTO 1

#define OPTION_SIGNAL 0
#define OPTION_KEYS 1
#define OPTION_DISPLAY 2
#define OPTION_SIGNAL 0
#define OPTION_KEY_REPEAT 1
#define OPTION_TICKER_SPEED 2
#define OPTION_TICKER_HOLD 3
#define OPTION_REC_FINALIZE 4

#define SELECT_MODE_EXIT 0xFF

Expand Down Expand Up @@ -292,7 +294,7 @@ uint8_t handle_option_value(const char* ptitle, const char* poption, uint16_t* p
int32_t cur_value = *pcur_value;
lcd_title_P(poption);

ultoa(cur_value, buffer, 10);
utoa((uint16_t)cur_value, buffer, 10);
lcd_status(buffer);

while (1) {
Expand All @@ -309,34 +311,67 @@ uint8_t handle_option_value(const char* ptitle, const char* poption, uint16_t* p
if (cur_value > max_value) {
cur_value = max_value;
}
ultoa(cur_value, buffer, 10);
utoa((uint16_t)cur_value, buffer, 10);
lcd_status(buffer);
break;
case COMMAND_PREVIOUS:
cur_value -= step_value;
if (cur_value < min_value) {
cur_value = min_value;
}
ultoa(cur_value, buffer, 10);
utoa((uint16_t)cur_value, buffer, 10);
lcd_status(buffer);
break;
}
}
}

void handle_mode_options() {
const char* ppitems[] = {S_OPTION_SIGNAL, S_OPTION_KEYS, S_OPTION_DISPLAY};
const char* ppitems[] = {S_OPTION_SIGNAL, S_OPTION_KEY_REPEAT, S_OPTION_TICKER_SPEED, S_OPTION_TICKER_HOLD, S_OPTION_REC_FINALIZE};
uint16_t value = 0;
uint8_t save = 0;

while (1) {
switch (handle_select_mode(S_MODE_OPTIONS, ppitems, 3)) {
switch (handle_select_mode(S_MODE_OPTIONS, ppitems, 5)) {
case OPTION_SIGNAL:
value = g_invert_signal;
if (handle_option_value(S_MODE_OPTIONS, S_OPTION_SIGNAL, &value, 0, 1, 1)) {
g_invert_signal = value;
save = 1;
}
break;
case OPTION_KEY_REPEAT:
value = g_key_repeat_next * 10;
if (handle_option_value(S_MODE_OPTIONS, S_OPTION_KEY_REPEAT, &value, 50, 500, 50)) {
g_key_repeat_next = value / 10;
save = 1;
}
break;
case OPTION_TICKER_SPEED:
value = g_ticker_rate * 10;
if (handle_option_value(S_MODE_OPTIONS, S_OPTION_TICKER_SPEED, &value, 50, 500, 50)) {
g_ticker_rate = value / 10;
save = 1;
}
break;
case OPTION_TICKER_HOLD:
value = g_ticker_hold * 10;
if (handle_option_value(S_MODE_OPTIONS, S_OPTION_TICKER_HOLD, &value, 250, 2500, 250)) {
g_ticker_hold = value / 10;
save = 1;
}
break;
case OPTION_REC_FINALIZE:
value = g_rec_finalize_time * 10;
if (handle_option_value(S_MODE_OPTIONS, S_OPTION_REC_FINALIZE, &value, 500, 2500, 500)) {
g_rec_finalize_time = value / 10;
save = 1;
}
break;
case SELECT_MODE_EXIT:
if (save) {
save_eeprom_data();
}
return;
break;
}
Expand Down
49 changes: 42 additions & 7 deletions tapuino.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
Expand Down Expand Up @@ -50,7 +51,13 @@ static uint32_t g_pulse_length = 0; // length of pulse in uS
static uint32_t g_pulse_length_save; // save length for read
static volatile uint32_t g_overflow; // write signal overflow timer detection
static volatile uint32_t g_timer_tick = 0; // timer tick at 100Hz (10 ms interval)

volatile uint8_t g_invert_signal = 0; // invert the signal for transmission/reception to/from a real Datasette
volatile uint16_t g_ticker_rate = TICKER_RATE / 10;
volatile uint16_t g_ticker_hold = TICKER_HOLD / 10;
volatile uint16_t g_key_repeat_start = KEY_REPEAT_START / 10;
volatile uint16_t g_key_repeat_next = KEY_REPEAT_NEXT / 10;
volatile uint16_t g_rec_finalize_time = REC_FINALIZE_TIME / 10;

uint32_t get_timer_tick() {
return g_timer_tick;
Expand Down Expand Up @@ -193,13 +200,17 @@ void signal_timer_start(uint8_t recording) {

if (recording) {
g_overflow = 0;
TCCR1B = _BV(ICES1) | _BV(CS11); // input capture, rising edge, pre-scaler 8 = 2 MHZ
TIMSK1 = _BV(ICIE1) | _BV(TOIE1); // input capture interrupt, overflow interrupt
if (g_invert_signal) {
TCCR1B = _BV(CS11); // input capture, FALLING edge, pre-scaler 8 = 2 MHZ
} else {
TCCR1B = _BV(ICES1) | _BV(CS11); // input capture, RISING edge, pre-scaler 8 = 2 MHZ
}
TIMSK1 = _BV(ICIE1) | _BV(TOIE1); // input capture interrupt enable, overflow interrupt enable
} else {
g_total_timer_count = 0;
TCCR1B |= _BV(CS11) | _BV(WGM12); // pre-scaler 8 = 2 MHZ, CTC Mode
TCCR1B |= _BV(CS11) | _BV(WGM12); // pre-scaler 8 = 2 MHZ, CTC Mode
OCR1A = 0xFFFF;
TIMSK1 |= _BV(OCIE1A); // output compare interrupt
TIMSK1 |= _BV(OCIE1A); // output compare interrupt
}
}

Expand Down Expand Up @@ -379,8 +390,8 @@ void record_file(char* pfile_name) {
while ((g_read_index & 0x80) == (g_write_index & 0x80)) {
// nasty bit of code to wait after the motor is shut off to finalise the TAP
if (MOTOR_IS_OFF()) {
// use the 100Hz timer to wait 5 seconds after the motor has shut off
if ((g_timer_tick - tmp) > (REC_FINALIZE_TIME / 10)) {
// use the 100Hz timer to wait some time after the motor has shut off
if ((g_timer_tick - tmp) > (uint32_t) g_rec_finalize_time) {
g_tap_file_complete = 1;
break;
}
Expand Down Expand Up @@ -430,18 +441,42 @@ void record_file(char* pfile_name) {
lcd_busy_spinner();
}


/*
int free_ram() {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
*/

void load_eeprom_data() {
if (eeprom_read_byte((uint8_t *) 0) == 0xE7) {
// g_invert_signal = eeprom_read_byte((uint8_t *) 1);
g_ticker_rate = eeprom_read_byte((uint8_t *) 2);
g_ticker_hold = eeprom_read_byte((uint8_t *) 3);
g_key_repeat_start = eeprom_read_byte((uint8_t *) 4);
g_key_repeat_next = eeprom_read_byte((uint8_t *) 5);
g_rec_finalize_time = eeprom_read_byte((uint8_t *) 6);
}
}

void save_eeprom_data() {
eeprom_write_byte((uint8_t *) 0, 0xE7);
// eeprom_write_byte((uint8_t *) 1, g_invert_signal);
eeprom_write_byte((uint8_t *) 2, g_ticker_rate);
eeprom_write_byte((uint8_t *) 3, g_ticker_hold);
eeprom_write_byte((uint8_t *) 4, g_key_repeat_start);
eeprom_write_byte((uint8_t *) 5, g_key_repeat_next);
eeprom_write_byte((uint8_t *) 6, g_rec_finalize_time);
}

int tapuino_hardware_setup(void)
{
FRESULT res;
uint8_t tmp;

load_eeprom_data();

// enable TWI pullups
TWI_PORT |= _BV(TWI_PIN_SDA);
TWI_PORT |= _BV(TWI_PIN_SCL);
Expand Down
5 changes: 5 additions & 0 deletions tapuino.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ void tapuino_run();
void record_file(char* pfile_name);
int play_file(FILINFO* pfile_info);
uint32_t get_timer_tick();
void save_eeprom_data();

extern volatile uint8_t g_invert_signal;
extern volatile uint8_t g_ticker_rate;
extern volatile uint8_t g_ticker_hold;
extern volatile uint8_t g_key_repeat_next;
extern volatile uint8_t g_rec_finalize_time;

#endif

0 comments on commit 3b4b88b

Please sign in to comment.