-
Notifications
You must be signed in to change notification settings - Fork 1
Stopwatch
Example of a stopwatch with displays for the last 5 results and the top 5 results.
The program is divided into 4 files:
// Standard libs
import "sys/os.c"
import "sys/stdlib.asm"
import "sys/string.asm"
import "lib/seg14.c"
import "lib/eeprom.c"
import "lib/techage.c"
// Configuration
const STRT = 0; // button
const STOP = 1; // button
const SEG1 = 8; // tenth
const SEG2 = 9; // seconds
const SEG3 = 10; // seconds
const SEG4 = 11; // minutes
const SEG5 = 12; // minutes
const LCD1 = 13; // last 5
const LCD2 = 14; // top 5
const MIN_DT = 100; // Minimum time: 1 min
const MAX_DT = 1800; // Maximum time: 3 min
The ports do not need to be adjusted if the I/O modules are configured as shown in the picture. Only the min/max timings have to be adjusted to your needs.
static var str[18];
func format_time(s, time) {
var tenth;
var sec;
var min;
tenth = time mod 10;
sec = (time / 10) mod 60;
min = (time / 600) mod 60;
s[0] = 48 + min / 10;
s[1] = 48 + min mod 10;
s[2] = ':';
s[3] = 48 + sec / 10;
s[4] = 48 + sec mod 10;
s[5] = '.';
s[6] = 48 + tenth;
s[7] = 0;
strpack(s);
return s;
}
func seg14_output_time(s) {
seg14_putchar(SEG5, s[0] >> 8);
seg14_putchar(SEG4, s[0] & 0xFF);
seg14_putchar(SEG3, s[1] & 0xFF);
seg14_putchar(SEG2, s[2] >> 8);
seg14_putchar(SEG1, s[3]);
}
func gen_string(name, time) {
strcpy(str, "<"); // left aligned
strcat(str, name);
str[8] = 0; // cut to long names
strcat(str, ": ");
strcat(str, time);
return str;
}
const ELE_SIZE = 20;
const TBL_SIZE = 100; // 5 * ELE_SIZE
static var top5[TBL_SIZE];
static func get_idx(dt) {
var idx = 0xFFFF;
var i;
for(i = 0; i < TBL_SIZE; i = i + ELE_SIZE) {
if(top5[i] == 0xFFFF) {
return i; // free entry
}
if(top5[i] == dt) {
return 0xFFFF; // already available
}
if(top5[i] > dt) {
dt = top5[i];
idx = i;
}
}
return idx;
}
func init_top5(port) {
var i;
clear_screen(port);
for(i = 0; i < TBL_SIZE; i = i + ELE_SIZE) {
e2p_read_block(i, &top5[i], ELE_SIZE);
}
}
func store_top5() {
var i;
for(i = 0; i < TBL_SIZE; i = i + ELE_SIZE) {
e2p_write_block(i, &top5[i], ELE_SIZE);
}
}
func output_top5(port) {
var line = 1;
var i;
for(i = 0; i < 5; i++) {
if(top5[i * ELE_SIZE] != 0xFFFF) {
write_line(port, line, &top5[i * ELE_SIZE + 1]);
line++;
}
}
}
func add_to_top5(s, dt) {
var idx = get_idx(dt);
if(idx != 0xFFFF) {
top5[idx] = dt;
strcpy(&top5[idx + 1], s);
store_top5();
}
}
// Application
import "sw_init.c"
import "sw_top5.c"
import "sw_time.c"
const WAITFOR_START = 0;
const WAITFOR_STOP = 1;
var sName1[10];
var sName2[10];
var sTime[8];
var Time;
var State;
var Cnt;
func start() {
var time;
if(input(STRT) == 1) {
request_data(STRT, 144, "", sName1);
request_data(STRT, 149, "", &time);
return time;
}
return 0;
}
func stop() {
var time;
if(input(STOP) == 1) {
request_data(STOP, 144, "", sName2);
request_data(STOP, 149, "", &time);
return time;
}
return 0;
}
func init() {
init_top5(LCD2);
output_top5(LCD2);
seg14_output_time("00:00.0");
State = WAITFOR_START;
Cnt = 0;
}
func loop() {
var t;
var time;
var dt;
var s;
var port;
port = get_next_inp_port();
if(port != 0xffff) {
if(State == WAITFOR_START) {
t = start();
if(t > 0) {
Time = t;
State = WAITFOR_STOP;
}
} else if(State == WAITFOR_STOP) {
t = stop();
if(t > 0) {
dt = t - Time;
if(dt > MIN_DT) {
if(strcmp(sName1, sName2) == 0) {
format_time(sTime, dt);
s = gen_string(sName1, sTime);
append_line(LCD1, s);
seg14_output_time(sTime);
add_to_top5(s, dt);
output_top5(LCD2);
State = WAITFOR_START;
}
}
}
}
}
if(State == WAITFOR_STOP) {
if((get_time() - Time) > MAX_DT) {
State = WAITFOR_START;
seg14_output_time("00:00.0");
} else {
Cnt++;
if(Cnt > 10) {
Cnt = 0;
dt = get_time() - Time;
format_time(sTime, dt);
seg14_output_time(sTime);
}
}
}
}
The stopwatch has a start and a stop button. The start button can be placed far away (The controller's map block does not need to be loaded for the clock to start, the timings are stored in the TA4 buttons).
Note: Both buttons must be configured with the open-end wrench (Techage Info Tool) so that they only send a "1" and no on/off sequence.
The stopwatch needs one I/O module, one Input module, and two techage XL displays.
The Beduino controller must be equipped with EEPROM chip to be able to store the top 5 result.
It uses the Beduino 14-Segment displays.