added more documentation

This commit is contained in:
Amy G. Bowersox 2019-12-07 13:07:59 -07:00
parent fc0c0f05fc
commit 7e098aa63a
15 changed files with 107 additions and 74 deletions

View File

@ -7,6 +7,7 @@
#include "scode.h"
#include "log.h"
/* command line options for UPIWIN */
static const struct option long_options[] = {
{"framebuffer", required_argument, 0, 'F'},
{"help", no_argument, 0, 'h'},
@ -16,6 +17,7 @@ static const struct option long_options[] = {
static const char *short_options = "F:hT:";
/* printed to stdout when upiwin is executed with -h/--help option */
static const char *helptext =
"UPIWIN - Micro Pi Windows server program\n\n"
"Usage: upiwin [options] scriptname [scriptargs]\n\n"
@ -25,19 +27,20 @@ static const char *helptext =
" -T,--touchscreen - Specifies the touchscreen device name\n"
"";
#define EXITFUNCBLOCK_FUNCCOUNT 64
#define EXITFUNCBLOCK_FUNCCOUNT 64 /* number of exit functions per function block */
/* exit functions are stored in these data blocks */
typedef struct tagEXITFUNCBLOCK
{
struct tagEXITFUNCBLOCK *next;
int num_funcs;
PEXITFUNC funcs[EXITFUNCBLOCK_FUNCCOUNT];
struct tagEXITFUNCBLOCK *next; /* chained in single linked list */
int num_funcs; /* number of functions this block contains */
PEXITFUNC funcs[EXITFUNCBLOCK_FUNCCOUNT]; /* pointers to functions */
} EXITFUNCBLOCK, *PEXITFUNCBLOCK;
/* The global configuration data */
GLOBAL_CONFIG Gconfig;
static PEXITFUNCBLOCK exitfuncs = NULL;
static PEXITFUNCBLOCK exitfuncs = NULL; /* pointer to head of exit function chain */
static void run_exit_funcs(void)
{
@ -50,6 +53,7 @@ static void run_exit_funcs(void)
exitfuncs = p->next;
for (i = p->num_funcs - 1; i >= 0; i--)
{
/* execute functions in LIFO order */
ASSERT(p->funcs[i]);
(*(p->funcs[i]))();
}
@ -59,6 +63,7 @@ static void run_exit_funcs(void)
static void init_defaults(void)
{
memset(&Gconfig, 0, sizeof(GLOBAL_CONFIG));
Gconfig.framebuffer_device = "/dev/fb1";
Gconfig.touchscreen_device = "/dev/input/touchscreen";
Gconfig.button_debounce = 100;
@ -79,7 +84,7 @@ static HRESULT parse_cmdline(int argc, char *argv[], GLOBAL_CONFIG *parsed)
break;
switch (c)
{
case 'F':
case 'F': /* frame buffer device name */
pstr = strdup(optarg);
if (!pstr)
{
@ -91,11 +96,11 @@ static HRESULT parse_cmdline(int argc, char *argv[], GLOBAL_CONFIG *parsed)
parsed->framebuffer_device = pstr;
break;
case 'h':
case 'h': /* show help */
help = TRUE;
break;
case 'T':
case 'T': /* touchscreen device name */
pstr = strdup(optarg);
if (!pstr)
{
@ -138,10 +143,16 @@ HRESULT Config_setup(int argc, char *argv[])
Log(LFATAL, "Unable to set up exit function mechanism");
return E_FAIL;
}
/* set defaults */
init_defaults();
/* evaluate command line */
hr = parse_cmdline(argc, argv, &from_commandline);
if (hr != S_OK)
return hr;
/* command line overrides everything */
overlay_config(&from_commandline);
return S_OK;
}

View File

@ -5,14 +5,15 @@
typedef void (*PEXITFUNC)(void);
/* global configuration data for UPIWIN */
typedef struct tagGLOBAL_CONFIG {
PCSTR framebuffer_device;
PCSTR touchscreen_device;
UINT32 button_debounce;
UINT32 sys_mq_length;
PCSTR framebuffer_device; /* name of frame buffer device */
PCSTR touchscreen_device; /* name of touchscreen device */
UINT32 button_debounce; /* minimum time between button up and next button down (ms) */
UINT32 sys_mq_length; /* length of system message queue */
} GLOBAL_CONFIG;
extern GLOBAL_CONFIG Gconfig;
extern GLOBAL_CONFIG Gconfig; /* one global configuration to rule them all */
extern HRESULT Config_setup(int argc, char *argv[]);
extern HRESULT Config_exitfunc(PEXITFUNC pfn);

View File

@ -16,12 +16,13 @@ extern uint8_t _binary_splash_bin_start[];
extern uint8_t _binary_splash_bin_end;
extern uint8_t _binary_splash_bin_size;
static int fb_fd = -1;
static int fb_fd = -1; /* framebuffer file descriptor */
/* frame buffer information */
static FBINFO local_info;
PCFBINFO Fb_Info = &local_info;
UINT16 *Fb_Ptr = NULL;
UINT16 *Fb_Ptr = NULL; /* pointer to memory-mapped frame buffer */
inline static UINT16 makemask(unsigned offset, unsigned length)
{
@ -30,12 +31,11 @@ inline static UINT16 makemask(unsigned offset, unsigned length)
static void do_cleanup(void)
{
/* additional cleanup here */
/* black out the display */
memset(Fb_Ptr, 0, local_info.screenbytes);
munmap((void *)Fb_Ptr, local_info.screenbytes);
Fb_Ptr = NULL;
munmap((void *)Fb_Ptr, local_info.screenbytes);
Fb_Ptr = NULL;
close(fb_fd);
fb_fd = -1;
}
@ -50,10 +50,11 @@ HRESULT Fb_setup(void)
if (fb_fd == -1)
{
hr = ERRNO_AS_SCODE;
Log(LFATAL, "Unable to open framebuffer (%08X)", hr);
Log(LFATAL, "Unable to open framebuffer device %s (%08X)", Gconfig.framebuffer_device, hr);
return hr;
}
/* fixed info is needed to get the memory parameters for the display */
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fixed))
{
hr = ERRNO_AS_SCODE;
@ -64,6 +65,7 @@ HRESULT Fb_setup(void)
local_info.linebytes = fixed.line_length;
local_info.screenbytes = fixed.smem_len;
/* variable info is used to get scren geometry and color info */
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &var))
{
hr = ERRNO_AS_SCODE;
@ -100,8 +102,6 @@ HRESULT Fb_setup(void)
/* display the splash screen */
memcpy(Fb_Ptr, _binary_splash_bin_start, (size_t)(&_binary_splash_bin_size));
/* additional setup here */
hr = Config_exitfunc(do_cleanup);
if (FAILED(hr))
do_cleanup();

View File

@ -3,28 +3,29 @@
#include "wintype.h"
/* info about the frame buffer */
typedef struct tagFBINFO {
UINT32 width;
UINT32 height;
UINT32 virtual_width;
UINT32 virtual_height;
UINT32 bpp;
UINT32 linebytes;
UINT32 screenbytes;
UINT16 red_offset;
UINT16 red_length;
UINT16 red_mask;
UINT16 green_offset;
UINT16 green_length;
UINT16 green_mask;
UINT16 blue_offset;
UINT16 blue_length;
UINT16 blue_mask;
UINT32 width; /* screen width */
UINT32 height; /* screen height */
UINT32 virtual_width; /* virtual screen width */
UINT32 virtual_height; /* virtual screen height */
UINT32 bpp; /* bits per pixel (16) */
UINT32 linebytes; /* number of bytes per line */
UINT32 screenbytes; /* number of bytes for the entire screen */
UINT16 red_offset; /* offset of "red" bits within pixel word (11) */
UINT16 red_length; /* number of "red" bits within pixel word (5) */
UINT16 red_mask; /* mask for the "red" bits in a pixel word */
UINT16 green_offset; /* offset of "green" bits within pixel word (5) */
UINT16 green_length; /* number of "green" bits within pixel word (6) */
UINT16 green_mask; /* mask for the "green" bits in a pixel word */
UINT16 blue_offset; /* offset of "blue" bits within pixel word (0) */
UINT16 blue_length; /* number of "blue" bits within pixel word (5) */
UINT16 blue_mask; /* mask for the "blue" bits in a pixel word */
} FBINFO;
typedef const FBINFO * const PCFBINFO;
extern PCFBINFO Fb_Info;
extern UINT16 *Fb_Ptr;
extern PCFBINFO Fb_Info; /* pointer to screen information */
extern UINT16 *Fb_Ptr; /* pointer to memory-mapped screen buffer */
extern HRESULT Fb_setup(void);
extern void Fb_clear(void);

View File

@ -25,6 +25,7 @@ void Fb_line(INT32 x1, INT32 y1, INT32 x2, INT32 y2, UINT16 color, BOOL xor)
INT32 dx = x2 - x1;
INT32 dy = y2 - y1;
/* uses Bresenham's line algorithm with fixed-point arithmetic */
if (ABS(dx) < ABS(dy))
{
if (y1 > y2)

View File

@ -3,6 +3,7 @@
#include "wintype.h"
/* Some predefined "primitive" color values */
#define FBPRIMCLR_BLACK 0x0000
#define FBPRIMCLR_RED 0xF800
#define FBPRIMCLR_GREEN 0x07E0

View File

@ -5,13 +5,14 @@
#include "scode.h"
#include "gpio.h"
/* GPIO lines used by various peripheral devices */
#define GLINE_BUTTON1 17
#define GLINE_BUTTON2 22
#define GLINE_BUTTON3 23
#define GLINE_BUTTON4 27
#define GLINE_BACKLIGHT 18
#define PWM_BACKLIGHT 0
#define PWM_BACKLIGHT 0 /* PWM channel used for backlight */
static void do_cleanup(void)
{

View File

@ -3,14 +3,15 @@
#include "wintype.h"
#define GPIO_BUTTON_COUNT 4
#define GPIO_BUTTON_COUNT 4 /* number of GPIO buttons we have */
/* state flags for the GPIO buttons */
#define GRB_STATE_BUTTON1 (1 << 0)
#define GRB_STATE_BUTTON2 (1 << 1)
#define GRB_STATE_BUTTON3 (1 << 2)
#define GRB_STATE_BUTTON4 (1 << 3)
#define GSB_BACKLIGHT_MAX 1023
#define GSB_BACKLIGHT_MAX 1023 /* maximum level for backlight */
extern HRESULT Gpio_setup(void);
extern UINT32 Gpio_read_buttons(void);

View File

@ -4,8 +4,11 @@
#include <sys/time.h>
#include "log.h"
/* string equivalents to the severity values */
static const char *severities[] = { "FATAL", "ERROR", "WARN ", "INFO ", "DEBUG" };
static FILE *logfile = stdout; /* log file pointer */
void Log(int level, const char *format, ...)
{
va_list argp;
@ -21,7 +24,7 @@ void Log(int level, const char *format, ...)
gettimeofday(&tv, NULL);
localtime_r(&(tv.tv_sec), &tm);
strftime(timestamp, 32, "%F %T", &tm);
printf("%s.%06u %s %s\n", timestamp, tv.tv_usec, severities[level], buf);
fprintf(logfile, "%s.%06u %s %s\n", timestamp, tv.tv_usec, severities[level], buf);
}
void Log_assert_failed(const char *test, const char *file, int line)

View File

@ -1,18 +1,21 @@
#ifndef __LOG_H_INCLUDED
#define __LOG_H_INCLUDED
#define LFATAL 0
#define LERROR 1
#define LWARN 2
#define LINFO 3
#define LDEBUG 4
/* Logging level severities */
#define LFATAL 0 /* fatal error */
#define LERROR 1 /* error */
#define LWARN 2 /* warning */
#define LINFO 3 /* information */
#define LDEBUG 4 /* debugging */
extern void Log(int level, const char *format, ...);
extern void Log_assert_failed(const char *test, const char *file, int line);
/* Current file name definitions for assert macros */
#define THIS_FILE __FILE__
#define DECLARE_THIS_FILE() static const char THIS_FILE[] = __FILE__
/* Assert macros */
#ifdef DEBUG_ASSERT
#define ASSERT(x) ((x) ? (void)0 : Log_assert_failed(#x, THIS_FILE, __LINE__))
#define VERIFY(x) ASSERT(x)

View File

@ -35,6 +35,7 @@ int main(int argc, char *argv[])
MSG msg;
char *tmp;
/* initialization sequence */
Time_init();
hr = Config_setup(argc, argv);
if (FAILED(hr))
@ -48,7 +49,7 @@ int main(int argc, char *argv[])
if (FAILED(Sys_enable_input()))
return EXIT_FAILURE;
Log(LINFO, "Pausing at startup.");
sleep(5); /* wait to show off splash screen */
sleep(3); /* wait to show off splash screen */
Fb_clear();
/* temporary drawing here */

View File

@ -1,22 +1,25 @@
#ifndef __MSG_QUEUE_H_INCLUDED
#define __MSG_QUEUE_H_INCLUDED
#include <pthread.h>
#include "wintype.h"
#include "msg.h"
/* internal structure of a message queue */
typedef struct tagMSG_QUEUE {
struct tagMSG_QUEUE *next;
PMSG startbound;
PMSG endbound;
PMSG head;
PMSG tail;
UINT32 nentries;
pthread_mutex_t mutex;
MSG messagestore[0];
struct tagMSG_QUEUE *next; /* allow us to be in a singly-linked list */
PMSG startbound; /* start boundary for message buffer */
PMSG endbound; /* end boundary for message buffer */
PMSG head; /* head pointer of message queue */
PMSG tail; /* tail pointer of message queue */
UINT32 nentries; /* number of entries possible in message buffer */
pthread_mutex_t mutex; /* controls access to queue from multiple threads */
MSG messagestore[0]; /* message buffer */
} MSG_QUEUE, *PMSG_QUEUE;
#define PEEK_REMOVE 0x0001
#define PEEK_NOREMOVE 0x0000
/* flags to Mq_peek */
#define PEEK_REMOVE 0x0001 /* remove message if found */
#define PEEK_NOREMOVE 0x0000 /* do not remove message if found */
extern PMSG_QUEUE Mq_alloc(UINT32 nentries);
extern void Mq_destroy(PMSG_QUEUE queue);

View File

@ -13,20 +13,22 @@
#include "gpio.h"
#include "time_func.h"
#define INPUT_EVENT_BATCH 16
#define INPUT_EVENT_BATCH 16 /* number of events to retrieve from touchscreen at once */
PMSG_QUEUE Sys_Queue = NULL;
PMSG_QUEUE Sys_Queue = NULL; /* system message queue */
static int ts_fd = 0; /* file descriptor for touchscreen */
static pthread_t ithread;
static volatile sig_atomic_t running = 1;
static int ts_fd = 0;
static pthread_t ithread; /* input thread handle */
static volatile sig_atomic_t running = 1; /* "running" flag for input thread */
static UINT32 last_bstate = 0;
static TIMESTAMP button_event_ok[GPIO_BUTTON_COUNT];
/* Local data for poll_buttons() */
static UINT32 last_bstate = 0; /* previous button state */
static TIMESTAMP button_event_ok[GPIO_BUTTON_COUNT]; /* timestamps to debounce events */
static UINT_PTR touch_x = 0;
static UINT_PTR touch_y = 0;
static UINT32 touch_nextmsg = WM_TOUCHMOVE;
/* Local data for poll_touchscreen() */
static UINT_PTR touch_x = 0; /* X coordinate to send with next message */
static UINT_PTR touch_y = 0; /* Y coordinate to send with next message */
static UINT32 touch_nextmsg = WM_TOUCHMOVE; /* identifier of next message to send */
static void poll_buttons(void)
{
@ -44,9 +46,10 @@ static void poll_buttons(void)
for (attr = 1, mask = GRB_STATE_BUTTON1; attr <= GPIO_BUTTON_COUNT; attr++, mask <<= 1)
{
if (now < button_event_ok[attr - 1])
continue;
continue; /* this is a "contact bounce" event, don't bother */
if (up & mask)
{
/* reset contact bounce timer - only seems to happen after button releases */
button_event_ok[attr - 1] = now + Gconfig.button_debounce;
Mq_post1(Sys_Queue, 0, WM_HWBUTTONUP, attr);
}
@ -75,10 +78,12 @@ static void poll_touchscreen(void)
Log(LERROR, "Unexpected end of file reading from touchscreen device");
return;
}
nev = nb / sizeof(struct input_event);
xerrno = nev * sizeof(struct input_event);
if (nb > xerrno)
Log(LERROR, "read %d bytes from touchscreen but we can only use %d", nb, xerrno);
for (i=0; i<nev; i++)
{
switch (buffer[i].type)
@ -111,6 +116,7 @@ static void poll_touchscreen(void)
static void *input_thread(void *arg)
{
/* clear all state at startup */
last_bstate = 0;
memset(button_event_ok, 0, GPIO_BUTTON_COUNT * sizeof(TIMESTAMP));
touch_x = touch_y = 0;
@ -151,7 +157,7 @@ HRESULT Sys_enable_input(void)
{
rc = ERRNO_AS_SCODE;
Mq_destroy(Sys_Queue);
Log(LFATAL, "Unable to open touchscreen device (%08X).", rc);
Log(LFATAL, "Unable to open touchscreen device %s (%08X).", Gconfig.touchscreen_device, rc);
return rc;
}

View File

@ -2,7 +2,7 @@
#include <sys/time.h>
#include "time_func.h"
static TIMESTAMP start_timestamp = 0;
static TIMESTAMP start_timestamp = 0; /* time since epoch at start of run */
TIMESTAMP Time_since_epoch(void)
{

View File

@ -32,7 +32,7 @@
#define INT64_BITS 64
#define UINT64_BITS 64
#define LOG_PTRSIZE 2 /* log2(sizeof(void *)) */
#define LOG_PTRSIZE 2 /* log2(sizeof(void *)) */
#define LOG_INTSIZE 2 /* log2(sizeof(int)) */
#define LOG_UINTSIZE 2 /* log2(sizeof(UINT32)) */