2019-04-05 13:59:05 +00:00
# define B15F_CLI_DEBUG
2019-04-05 06:33:31 +00:00
2019-04-03 13:20:49 +00:00
# include <stdio.h>
# include <ncurses.h> // sudo apt-get install libncurses5-dev
2019-04-03 14:15:35 +00:00
# include <vector>
# include <string>
# include <iostream>
2019-04-04 14:16:28 +00:00
# include <signal.h>
2019-04-03 14:15:35 +00:00
# include <sys/ioctl.h>
# include <unistd.h>
2019-04-04 14:16:28 +00:00
# include <signal.h>
2019-04-05 11:29:14 +00:00
# include <future>
# include <thread>
# include <chrono>
2019-04-05 06:33:31 +00:00
# include "ui/view_selection.h"
2019-04-04 11:19:11 +00:00
# include "ui/view_info.h"
2019-04-05 06:47:06 +00:00
# include "ui/view_monitor.h"
2019-04-05 10:07:26 +00:00
# include "ui/view_promt.h"
2019-04-05 08:38:59 +00:00
# include "drv/b15f.h"
2019-04-03 13:20:49 +00:00
2019-04-04 14:16:28 +00:00
// global error message
std : : string ERR_MSG ;
2019-04-03 13:20:49 +00:00
2019-04-04 11:19:11 +00:00
std : : vector < View * > win_stack ;
2019-04-04 14:16:28 +00:00
2019-04-05 11:29:14 +00:00
volatile int win_changed_cooldown = 0 ;
volatile bool t_refresh_active = false ;
std : : thread t_refresh ;
2019-04-04 14:16:28 +00:00
void cleanup ( )
{
2019-04-05 11:29:14 +00:00
if ( t_refresh . joinable ( ) )
t_refresh . join ( ) ;
2019-04-04 14:16:28 +00:00
clrtoeol ( ) ;
refresh ( ) ;
endwin ( ) ;
}
void signal_handler ( int signal )
{
if ( signal = = SIGWINCH )
{
2019-04-05 11:29:14 +00:00
win_changed_cooldown = 10 ; // 100ms
if ( ! t_refresh_active )
2019-04-04 14:16:28 +00:00
{
2019-04-05 11:29:14 +00:00
if ( t_refresh . joinable ( ) )
t_refresh . join ( ) ;
t_refresh_active = true ;
t_refresh = std : : thread ( [ ] ( ) {
while ( win_changed_cooldown - - )
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 10 ) ) ;
t_refresh_active = false ;
if ( win_stack . size ( ) )
win_stack . back ( ) - > repaint ( ) ;
} ) ;
2019-04-04 14:16:28 +00:00
}
2019-04-05 11:29:14 +00:00
2019-04-04 14:16:28 +00:00
}
else if ( signal = = SIGINT )
{
cleanup ( ) ;
std : : cout < < " SIGINT - Abbruch. " < < std : : endl ;
if ( ERR_MSG . length ( ) )
std : : cout < < " ERR_MSG: " < < ERR_MSG < < std : : endl ;
exit ( EXIT_FAILURE ) ;
}
}
2019-04-03 13:20:49 +00:00
2019-04-04 11:19:11 +00:00
void init ( )
2019-04-03 14:15:35 +00:00
{
2019-04-04 14:16:28 +00:00
// init b15 driver
2019-04-05 08:38:59 +00:00
B15F : : getInstance ( ) ;
2019-04-05 13:59:05 +00:00
# ifndef B15F_CLI_DEBUG
2019-04-05 11:29:14 +00:00
std : : cout < < std : : endl < < " Starte in 3s ... " < < std : : endl ;
2019-04-05 13:04:59 +00:00
sleep ( 3 ) ;
2019-04-05 13:59:05 +00:00
# endif
2019-04-04 14:16:28 +00:00
// init all ncurses stuff
2019-04-04 11:19:11 +00:00
initscr ( ) ;
start_color ( ) ;
curs_set ( 0 ) ; // 0: invisible, 1: normal, 2: very visible
clear ( ) ;
noecho ( ) ;
cbreak ( ) ; // Line buffering disabled. pass on everything
mousemask ( ALL_MOUSE_EVENTS , NULL ) ;
2019-04-03 14:15:35 +00:00
2019-04-04 14:16:28 +00:00
// connect signals to handler
signal ( SIGWINCH , signal_handler ) ;
signal ( SIGINT , signal_handler ) ;
// set view context
2019-04-05 08:38:59 +00:00
View : : setWinContext ( newwin ( 25 , 85 , 0 , 0 ) ) ;
2019-04-03 14:15:35 +00:00
}
2019-04-04 14:16:28 +00:00
void finish ( int )
2019-04-04 11:19:11 +00:00
{
cleanup ( ) ;
exit ( EXIT_SUCCESS ) ;
}
2019-04-03 14:15:35 +00:00
2019-04-05 10:07:26 +00:00
void view_back ( int )
{
2019-04-05 12:33:15 +00:00
if ( win_stack . size ( ) )
{
delete win_stack . back ( ) ;
win_stack . pop_back ( ) ;
}
2019-04-05 10:07:26 +00:00
if ( win_stack . size ( ) )
win_stack . back ( ) - > repaint ( ) ;
}
2019-04-04 14:16:28 +00:00
void input ( int )
2019-04-04 11:19:11 +00:00
{
2019-04-05 12:33:15 +00:00
call_t nextCall ;
2019-04-04 11:19:11 +00:00
int key ;
do
{
key = wgetch ( View : : getWinContext ( ) ) ;
2019-04-05 10:07:26 +00:00
win_stack . back ( ) - > repaint ( ) ;
2019-04-04 11:19:11 +00:00
nextCall = win_stack . back ( ) - > keypress ( key ) ;
if ( key = = - 1 )
2019-04-05 10:07:26 +00:00
view_back ( key ) ;
2019-04-04 11:19:11 +00:00
if ( nextCall )
nextCall ( key ) ;
2019-04-03 14:15:35 +00:00
}
2019-04-05 10:07:26 +00:00
while ( win_stack . size ( ) ) ;
2019-04-04 11:19:11 +00:00
}
2019-04-04 14:16:28 +00:00
void show_info ( int )
2019-04-04 11:19:11 +00:00
{
2019-04-04 14:16:28 +00:00
ViewInfo * view = new ViewInfo ( ) ;
2019-04-04 11:19:11 +00:00
view - > setTitle ( " Info " ) ;
2019-04-05 12:33:15 +00:00
view - > setText ( " Informationen zu Board 15 Famulus Edition \n Es war einmal... " ) ;
2019-04-04 14:16:28 +00:00
view - > setLabelClose ( " [ Zurueck ] " ) ;
2019-04-04 11:19:11 +00:00
view - > repaint ( ) ;
win_stack . push_back ( view ) ;
input ( 0 ) ;
}
2019-04-05 06:47:06 +00:00
void show_monitor ( int )
{
ViewMonitor * view = new ViewMonitor ( ) ;
view - > setTitle ( " Monitor " ) ;
2019-04-05 08:38:59 +00:00
view - > setText ( " \n Erfasse Messwerte... " ) ;
2019-04-05 06:47:06 +00:00
view - > setLabelClose ( " [ Zurueck ] " ) ;
view - > repaint ( ) ;
win_stack . push_back ( view ) ;
input ( 0 ) ;
}
2019-04-05 10:07:26 +00:00
void show_invalid_port_input ( int )
{
ViewInfo * view = new ViewInfo ( ) ;
view - > setTitle ( " Falsche Eingabe " ) ;
2019-04-05 10:52:51 +00:00
view - > setText ( " Bitte geben Sie einen Wert aus dem Intervall [0, FF] an. " ) ;
view - > setLabelClose ( " [ Schliessen ] " ) ;
view - > repaint ( ) ;
win_stack . push_back ( view ) ;
input ( 0 ) ;
}
void show_invalid_dac_input ( int )
{
ViewInfo * view = new ViewInfo ( ) ;
view - > setTitle ( " Falsche Eingabe " ) ;
view - > setText ( " Bitte geben Sie einen Wert aus dem Intervall [0, 1023] an. " ) ;
2019-04-05 10:07:26 +00:00
view - > setLabelClose ( " [ Schliessen ] " ) ;
view - > repaint ( ) ;
win_stack . push_back ( view ) ;
input ( 0 ) ;
}
void write_digital_output0 ( int )
{
try
{
2019-04-05 12:33:15 +00:00
int d = std : : stoi ( static_cast < ViewPromt * > ( win_stack . back ( ) ) - > getInput ( ) , 0 , 16 ) ;
if ( d > 255 | | 0 > d )
throw std : : invalid_argument ( " bad value " ) ;
uint8_t port = static_cast < uint8_t > ( d ) ;
2019-04-05 10:07:26 +00:00
B15F & drv = B15F : : getInstance ( ) ;
drv . digitalWrite0 ( port ) ;
view_back ( 0 ) ;
}
catch ( std : : invalid_argument & ex )
{
show_invalid_port_input ( 0 ) ;
}
}
void write_digital_output1 ( int )
{
try
{
2019-04-05 12:33:15 +00:00
int d = std : : stoi ( static_cast < ViewPromt * > ( win_stack . back ( ) ) - > getInput ( ) , 0 , 16 ) ;
if ( d > 255 | | 0 > d )
throw std : : invalid_argument ( " bad value " ) ;
uint8_t port = static_cast < uint8_t > ( d ) ;
2019-04-05 10:07:26 +00:00
B15F & drv = B15F : : getInstance ( ) ;
drv . digitalWrite1 ( port ) ;
view_back ( 0 ) ;
}
catch ( std : : invalid_argument & ex )
{
show_invalid_port_input ( 0 ) ;
}
}
2019-04-05 10:52:51 +00:00
void write_analog_output0 ( int )
{
try
{
uint16_t port = std : : stoi ( static_cast < ViewPromt * > ( win_stack . back ( ) ) - > getInput ( ) ) ;
if ( port > 1023 )
throw std : : invalid_argument ( " bad value " ) ;
B15F & drv = B15F : : getInstance ( ) ;
drv . analogWrite0 ( port ) ;
view_back ( 0 ) ;
}
catch ( std : : invalid_argument & ex )
{
show_invalid_dac_input ( 0 ) ;
}
}
void write_analog_output1 ( int )
{
try
{
uint16_t port = std : : stoi ( static_cast < ViewPromt * > ( win_stack . back ( ) ) - > getInput ( ) ) ;
if ( port > 1023 )
throw std : : invalid_argument ( " bad value " ) ;
B15F & drv = B15F : : getInstance ( ) ;
drv . analogWrite1 ( port ) ;
view_back ( 0 ) ;
}
catch ( std : : invalid_argument & ex )
{
show_invalid_dac_input ( 0 ) ;
}
}
2019-04-05 10:07:26 +00:00
void show_digital_output0 ( int )
{
ViewPromt * view = new ViewPromt ( ) ;
view - > setTitle ( " Digitale Ausgabe BE0 " ) ;
2019-04-05 13:04:59 +00:00
view - > setMessage ( " \n Ausgabe Port-Wert (hex): 0x " ) ;
2019-04-05 10:07:26 +00:00
view - > setCancel ( " [ Zurueck ] " , true ) ;
view - > setConfirm ( " [ OK ] " , & write_digital_output0 ) ;
view - > repaint ( ) ;
win_stack . push_back ( view ) ;
input ( 0 ) ;
}
void show_digital_output1 ( int )
{
ViewPromt * view = new ViewPromt ( ) ;
view - > setTitle ( " Digitale Ausgabe BE1 " ) ;
2019-04-05 13:04:59 +00:00
view - > setMessage ( " \n Ausgabe Port-Wert (hex): 0x " ) ;
2019-04-05 10:07:26 +00:00
view - > setCancel ( " [ Zurueck ] " , true ) ;
view - > setConfirm ( " [ OK ] " , & write_digital_output1 ) ;
view - > repaint ( ) ;
win_stack . push_back ( view ) ;
input ( 0 ) ;
}
2019-04-05 10:52:51 +00:00
void show_analog_output0 ( int )
{
ViewPromt * view = new ViewPromt ( ) ;
view - > setTitle ( " Analoge Ausgabe AA0 " ) ;
2019-04-05 13:04:59 +00:00
view - > setMessage ( " \n Ausgabe 10-Bit-Wert (0...1023): " ) ;
2019-04-05 10:52:51 +00:00
view - > setCancel ( " [ Zurueck ] " , true ) ;
view - > setConfirm ( " [ OK ] " , & write_analog_output0 ) ;
view - > repaint ( ) ;
win_stack . push_back ( view ) ;
input ( 0 ) ;
}
void show_analog_output1 ( int )
{
ViewPromt * view = new ViewPromt ( ) ;
view - > setTitle ( " Analoge Ausgabe AA1 " ) ;
2019-04-05 13:04:59 +00:00
view - > setMessage ( " \n Ausgabe 10-Bit-Wert (0...1023): " ) ;
2019-04-05 10:52:51 +00:00
view - > setCancel ( " [ Zurueck ] " , true ) ;
view - > setConfirm ( " [ OK ] " , & write_analog_output1 ) ;
view - > repaint ( ) ;
win_stack . push_back ( view ) ;
input ( 0 ) ;
}
2019-04-05 12:33:15 +00:00
void stop_selftest ( int )
{
B15F & drv = B15F : : getInstance ( ) ;
drv . discard ( ) ;
}
void start_selftest ( int )
{
B15F & drv = B15F : : getInstance ( ) ;
drv . activateSelfTestMode ( ) ;
ViewInfo * view = new ViewInfo ( ) ;
view - > setTitle ( " Selbsttest aktiv " ) ;
view - > setText ( " Das B15 befindet sich jetzt im Selbsttestmodus. \n \n Selbsttest: \n Zu Beginn geht der Reihe nach jede LED von BA0 bis BA1 an. \n Danach leuchten die LEDs an AA0 und AA1 kurz auf. \n Zum Schluss spiegelt in einer Endlosschleife: \n * BA0 Port BE0 \n * BA1 die DIP-Schalter S7 \n * AA0 ADC0 \n * AA1 ADC1 " ) ;
view - > setLabelClose ( " [ Selbsttest Beenden ] " ) ;
view - > setCall ( & stop_selftest ) ;
view - > repaint ( ) ;
win_stack . push_back ( view ) ;
input ( 0 ) ;
}
void show_selftest ( int )
{
ViewInfo * view = new ViewInfo ( ) ;
view - > setTitle ( " Selbsttest " ) ;
view - > setText ( " Bitte entfernen Sie jetzt alle Draehte von den Anschlussklemmen und bestaetigen \n mit Enter. " ) ;
view - > setLabelClose ( " [ Weiter ] " ) ;
view - > setCall ( & start_selftest ) ;
view - > repaint ( ) ;
win_stack . push_back ( view ) ;
input ( 0 ) ;
}
2019-04-04 14:16:28 +00:00
void show_main ( int )
2019-04-04 11:19:11 +00:00
{
2019-04-05 06:33:31 +00:00
ViewSelection * view = new ViewSelection ( ) ;
2019-04-04 11:19:11 +00:00
view - > setTitle ( " B15F - Command Line Interface " ) ;
2019-04-05 06:47:06 +00:00
view - > addChoice ( " [ Monitor - Eingaben beobachten ] " , & show_monitor ) ;
2019-04-05 10:07:26 +00:00
view - > addChoice ( " [ Digitale Ausgabe BE0 ] " , & show_digital_output0 ) ;
view - > addChoice ( " [ Digitale Ausgabe BE1 ] " , & show_digital_output1 ) ;
2019-04-05 10:52:51 +00:00
view - > addChoice ( " [ Analoge Ausgabe AA0 ] " , & show_analog_output0 ) ;
view - > addChoice ( " [ Analoge Ausgabe AA1 ] " , & show_analog_output1 ) ;
2019-04-05 12:33:15 +00:00
view - > addChoice ( " [ Selbsttest des B15 ] " , & show_selftest ) ;
2019-04-05 06:33:31 +00:00
view - > addChoice ( " [ Informationen ] " , & show_info ) ;
view - > addChoice ( " " , nullptr ) ;
view - > addChoice ( " [ Beenden ] " , & finish ) ;
2019-04-04 11:19:11 +00:00
view - > repaint ( ) ;
win_stack . push_back ( view ) ;
input ( 0 ) ;
2019-04-03 14:15:35 +00:00
}
2019-04-03 13:20:49 +00:00
int main ( )
2019-04-04 11:19:11 +00:00
{
init ( ) ;
2019-04-03 14:15:35 +00:00
2019-04-04 11:19:11 +00:00
show_main ( 0 ) ;
cleanup ( ) ;
return EXIT_SUCCESS ;
2019-04-03 13:20:49 +00:00
}