Message Box added to GUI. Connection code and timers are having issues.

This commit is contained in:
Scott Duensing 2021-11-28 21:32:07 -06:00
parent eb9c13d5b2
commit a4a8534aa6
31 changed files with 739 additions and 72 deletions

View file

@ -27,7 +27,10 @@ CONFIG -= qt
DESTDIR = $$OUT_PWD/bin
SHARED = $$PWD/../shared
DOS_HEADERS =
QMAKE_CFLAGS += -O0
DOS_HEADERS = \
src/thirdparty/serial/serial.h
DOS_SOURCES = \
src/thirdparty/serial/serial.c \
@ -62,6 +65,7 @@ HEADERS = \
$$SHARED/primes.h \
src/config.h \
$$SHARED/util.h \
src/gui/msgbox.h \
src/thirdparty/minicoro/minicoro.h \
src/system/comport.h \
src/settings.h \
@ -103,7 +107,9 @@ SOURCES = \
$$SHARED/thirdparty/ini/src/ini.c \
src/config.c \
$$SHARED/memory.c \
src/gui/msgbox.c \
src/settings.c \
src/system/comport.c \
src/system/surface.c \
src/system/taglist.c \
$$SHARED/util.c \

BIN
client/data/IconError.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/IconInformation.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/IconMessage.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/IconQuestion.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/IconWarning.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/MessageBoxIcon.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/mbie32.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/mbii32.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/mbim32.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/mbiq32.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/mbiw32.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -65,11 +65,12 @@ static char *_magicDebugNames[MAGIC_COUNT] = {
};
static void guiDeleteList(void);
static void guiDeleteListItem(WidgetT **widget);
static void guiPaintBoundsGet(WidgetT *widget, RectT *pos);
static void guiKeyboardChildrenProcess(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
static uint8_t guiMouseChildrenProcess(WidgetT *widget, MouseT *mouse);
static void guiDeleteList(void);
static void guiDeleteListItem(WidgetT **widget);
static void guiPaintBoundsGet(WidgetT *widget, RectT *pos);
static void guiKeyboardChildrenProcess(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
static uint8_t guiMouseChildrenProcess(WidgetT *widget, MouseT *mouse);
static WindowT *guiWindowFindTopChildrenProcess(WidgetT *widget);
void guiAttach(WidgetT *parent, WidgetT *child) {
@ -153,7 +154,12 @@ void guiDebugAreaShow(WidgetT *widget) {
RectT r;
guiWidgetBoundsDrawableOnScreenGet(widget, &r);
logWrite("%s: %dx%d\n", _magicDebugNames[widget->magic], r.w, r.h);
logWrite("%s: Size %dx%d Area %dx%d TL %dx%d BR %dx%d\n",
_magicDebugNames[widget->magic],
widget->pos.w, widget->pos.h,
r.w, r.h,
widget->margin.x, widget->margin.y,
widget->margin.w, widget->margin.h);
}
@ -191,7 +197,8 @@ void guiDelete(WidgetT **widget) {
static void guiDeleteList(void) {
WidgetT **w = NULL;
WidgetT **w = NULL;
WindowT *win = NULL;
while (arrlen(_guiDeleteList) > 0) {
w = arrpop(_guiDeleteList);
@ -200,6 +207,14 @@ static void guiDeleteList(void) {
arrfree(_guiDeleteList);
_guiDeleteList = NULL;
// Is the top level window no longer active? If so, select it.
win = guiWindowFindTop();
if (win) {
if (!GUI_GET_FLAG(W(win), WIDGET_FLAG_ACTIVE)) {
windowActiveSet(win);
}
}
}
@ -686,3 +701,32 @@ void guiWidgetPositionOnScreenGet(WidgetT *widget, RectT *pos) {
}
}
WindowT *guiWindowFindTop(void) {
if (guiRootGet() == NULL) return NULL;
return guiWindowFindTopChildrenProcess(guiRootGet());
}
static WindowT *guiWindowFindTopChildrenProcess(WidgetT *widget) {
size_t len = arrlenu(widget->children);
size_t x;
WindowT *top = NULL;
WindowT *r = NULL;
// Is this a window?
if (widget->magic == MAGIC_WINDOW) {
top = (WindowT *)widget;
}
// Check children.
if (len > 0) {
for (x=0; x<len; x++) {
r = guiWindowFindTopChildrenProcess(widget->children[x]);
if (r) top = r;
}
}
return top;
}

View file

@ -213,6 +213,7 @@ void guiUserDataSet(WidgetT *widget, void *userData);
void guiWidgetAndChildrenDirtySet(WidgetT *widget);
void guiWidgetBoundsDrawableOnScreenGet(WidgetT *widget, RectT *bounds);
void guiWidgetPositionOnScreenGet(WidgetT *widget, RectT *pos);
WindowT *guiWindowFindTop(void);
#endif // GUI_H

219
client/src/gui/msgbox.c Normal file
View file

@ -0,0 +1,219 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "msgbox.h"
#include "font.h"
#include "window.h"
#include "button.h"
#include "label.h"
#include "picture.h"
#define WIN_MARGIN_TOP 26
#define WIN_MARGIN_LEFT 7
#define WIN_MARGIN_RIGHT 8
#define WIN_MARGIN_BOTTOM 8
#define BTN_MARGIN_TOP 4
#define BTN_MARGIN_LEFT 14
#define BTN_MARGIN_RIGHT 14
#define BTN_MARGIN_BOTTOM 4
#define MSG_PADDING 10
#define ICN_SIZE 32
static msgBoxCallback cbOne = NULL;
static msgBoxCallback cbTwo = NULL;
static msgBoxCallback cbThree = NULL;
static WindowT *winDialog = NULL;
static PictureT *picIcon = NULL;
static LabelT *lblText = NULL;
static ButtonT *btnOne = NULL;
static ButtonT *btnTwo = NULL;
static ButtonT *btnThree = NULL;
static void btnMsgBox(WidgetT *widget);
static char *iconFiles[MSGBOX_ICON_COUNT] = {
"data/mbie32.png",
"data/mbiw32.png",
"data/mbii32.png",
"data/mbim32.png",
"data/mbiq32.png"
};
static void btnMsgBox(WidgetT *widget) {
// Remove us from the display.
guiDelete(D(winDialog));
// Call whoever wanted called.
if (widget == W(btnOne)) {
if (cbOne) cbOne(MSGBOX_BUTTON_ONE);
}
if (widget == W(btnTwo)) {
if (cbTwo) cbTwo(MSGBOX_BUTTON_TWO);
}
if (widget == W(btnThree)) {
if (cbThree) cbThree(MSGBOX_BUTTON_THREE);
}
}
void msgBoxOne(char *title, MsgBoxIconT icon, char *message, char *buttonOne, msgBoxCallback callbackOne) {
return msgBoxThree(title, icon, message, buttonOne, callbackOne, NULL, NULL, NULL, NULL);
}
void msgBoxThree(char *title, MsgBoxIconT icon, char *message, char *buttonOne, msgBoxCallback callbackOne, char *buttonTwo, msgBoxCallback callbackTwo, char *buttonThree, msgBoxCallback callbackThree) {
uint16_t w = 0;
uint16_t h = 0;
uint16_t x = 0;
uint16_t y = 0;
uint16_t t = 0;
uint16_t textH = 0;
uint16_t textW = 0;
uint16_t iconW = 0;
uint16_t newW = 0;
uint16_t cursorH = 0;
char *token = NULL;
char *text = NULL;
// Null these for later.
btnOne = NULL;
btnTwo = NULL;
btnThree = NULL;
// Remember callbacks for later.
cbOne = callbackOne;
cbTwo = callbackTwo;
cbThree = callbackThree;
// Calculate size of dialog box window.
// Initial minimum window width is the left and right margins + font width * (title length + 3).
w = WIN_MARGIN_LEFT + WIN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * (strlen(title) + 3));
// Initial minimum window height is the top and bottom margins + font height + button height + (padding * 2).
h = WIN_MARGIN_TOP + WIN_MARGIN_BOTTOM + fontHeightGet(_guiFont) + (BTN_MARGIN_TOP + BTN_MARGIN_BOTTOM + fontHeightGet(_guiFont)) + (MSG_PADDING * 2);
// Count lines of text and add up height. Find widest line.
text = strdup(message);
token = strtok(text, "\n");
while (token) {
textH += fontHeightGet(_guiFont);
if (strlen(token) > textW) {
textW = strlen(token);
}
token = strtok(NULL, "\n");
}
free(text);
textW *= fontWidthGet(_guiFont);
// Initial cursor move and window sizing are based on text height.
cursorH = textH;
// Is there an icon?
if (icon > MSGBOX_ICON_NONE && icon < MSGBOX_ICON_COUNT) {
// Is the icon taller than the message text?
if (ICN_SIZE > textH) {
// Use icon height.
cursorH = ICN_SIZE;
}
iconW = ICN_SIZE + MSG_PADDING;
}
// Add icon and/or text height to window.
h += cursorH;
// Do we need to make the dialog wider to contain the text and icon?
newW = WIN_MARGIN_LEFT + WIN_MARGIN_RIGHT + iconW + textW + (MSG_PADDING * 2); // Only 2 here because iconW includes one.
if (newW > w) w = newW;
// Do we need to make the dialog wider to contain the buttons?
newW = WIN_MARGIN_LEFT + WIN_MARGIN_RIGHT + MSG_PADDING + BTN_MARGIN_LEFT + BTN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * strlen(buttonOne));
if (buttonTwo) newW += MSG_PADDING + BTN_MARGIN_LEFT + BTN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * strlen(buttonTwo));
if (buttonThree) newW += MSG_PADDING + BTN_MARGIN_LEFT + BTN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * strlen(buttonThree));
if (newW > w) w = newW;
// Draw dialog.
h -= 5; // Height is off for some reason. At least, to me, it doesn't look right.
winDialog = windowNew(vbeDisplayWidthGet() / 2 - w / 2, vbeDisplayHeightGet() / 2 - h / 2, w, h, title);
guiAttach(guiRootGet(), W(winDialog));
// Initial x cursor is the (implied window left margin +) padding
x = MSG_PADDING;
// Initial y cursor is the (implied window top margin +) padding
y = MSG_PADDING;
// Load proper icon, if desired.
if (icon > MSGBOX_ICON_NONE && icon < MSGBOX_ICON_COUNT) {
picIcon = pictureNew(x, y, iconFiles[icon - 1]);
guiAttach(W(winDialog), W(picIcon));
}
// Draw message text.
t = y;
x += iconW;
text = strdup(message);
token = strtok(text, "\n");
while (token) {
lblText = labelNew(x, t, token);
guiAttach(W(winDialog), W(lblText));
t += fontHeightGet(_guiFont);
token = strtok(NULL, "\n");
}
free(text);
// Move to where buttons belong.
x = w - (WIN_MARGIN_LEFT + WIN_MARGIN_RIGHT + BTN_MARGIN_LEFT + BTN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * strlen(buttonOne)));
y += cursorH + MSG_PADDING;
// We always have at least one button.
btnOne = buttonNew(x, y, buttonOne, btnMsgBox);
guiAttach(W(winDialog), W(btnOne));
// Two buttons?
if (buttonTwo) {
x -= (MSG_PADDING + BTN_MARGIN_LEFT + BTN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * strlen(buttonTwo)));
btnTwo = buttonNew(x, y, buttonTwo, btnMsgBox);
guiAttach(W(winDialog), W(btnTwo));
}
// Three buttons?
if (buttonThree) {
x -= (MSG_PADDING + BTN_MARGIN_LEFT + BTN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * strlen(buttonThree)));
btnThree = buttonNew(x, y, buttonThree, btnMsgBox);
guiAttach(W(winDialog), W(btnThree));
}
}
void msgBoxTwo(char *title, MsgBoxIconT icon, char *message, char *buttonOne, msgBoxCallback callbackOne, char *buttonTwo, msgBoxCallback callbackTwo) {
return msgBoxThree(title, icon, message, buttonOne, callbackOne, buttonTwo, callbackTwo, NULL, NULL);
}

57
client/src/gui/msgbox.h Normal file
View file

@ -0,0 +1,57 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef MSGBOX_H
#define MSGBOX_H
#include "os.h"
#include "widget.h"
enum MsgBoxIconE {
MSGBOX_ICON_NONE = 0,
MSGBOX_ICON_ERROR,
MSGBOX_ICON_WARNING,
MSGBOX_ICON_INFORMATION,
MSGBOX_ICON_MESSAGE,
MSGBOX_ICON_QUESTION,
MSGBOX_ICON_COUNT
};
enum MsgBoxButtonE {
MSGBOX_BUTTON_ONE = 0,
MSGBOX_BUTTON_TWO,
MSGBOX_BUTTON_THREE,
MSGBOX_BUTTON_COUNT
};
typedef enum MsgBoxIconE MsgBoxIconT;
typedef enum MsgBoxButtonE MsgBoxButtonT;
typedef void (*msgBoxCallback)(MsgBoxButtonT button);
void msgBoxOne(char *title, MsgBoxIconT icon, char *message, char *buttonOne, msgBoxCallback callbackOne);
void msgBoxThree(char *title, MsgBoxIconT icon, char *message, char *buttonOne, msgBoxCallback callbackOne, char *buttonTwo, msgBoxCallback callbackTwo, char *buttonThree, msgBoxCallback callbackThree);
void msgBoxTwo(char *title, MsgBoxIconT icon, char *message, char *buttonOne, msgBoxCallback callbackOne, char *buttonTwo, msgBoxCallback callbackTwo);
#endif // MSGBOX_H

View file

@ -289,7 +289,7 @@ static void textboxPaint(WidgetT *widget, uint8_t enabled, RectT pos) {
free(draw);
// Draw cursor.
if (guiFocusGet() == widget && timerQuarterSecondOn) {
if (guiFocusGet() == widget && _timerQuarterSecondOn) {
caretPos = textX + fontWidthGet(_guiFont) * t->caret;
fontRender(_guiFont, cursor, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], caretPos, textY);
}

View file

@ -307,7 +307,7 @@ static void updownPaint(WidgetT *widget, uint8_t enabled, RectT pos) {
fontRender(_guiFont, draw, _guiColor[COLOR_UPDOWN_TEXT], _guiColor[COLOR_UPDOWN_BACKGROUND], textX, textY);
// Draw cursor.
if (guiFocusGet() == widget && timerQuarterSecondOn) {
if (guiFocusGet() == widget && _timerQuarterSecondOn) {
textX += (strlen(draw) - 1) * fontWidthGet(_guiFont);
fontRender(_guiFont, cursor, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], textX, textY);
}

View file

@ -76,6 +76,26 @@ WidgetT *widgetInit(WidgetT *widget, uint8_t magic, uint16_t x, uint16_t y, uint
}
uint16_t widgetMarginBottomGet(WidgetT *widget) {
return widget->margin.h;
}
uint16_t widgetMarginLeftGet(WidgetT *widget) {
return widget->margin.x;
}
uint16_t widgetMarginRightGet(WidgetT *widget){
return widget->margin.w;
}
uint16_t widgetMarginTopGet(WidgetT *widget) {
return widget->margin.y;
}
WidgetT *widgetNew(uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t marginX, uint16_t marginY, uint16_t marginX2, uint16_t marginY2) {
WidgetT *widget = (WidgetT *)malloc(sizeof(WidgetT));

View file

@ -70,6 +70,10 @@ uint8_t widgetEnableGet(WidgetT *widget);
void widgetEnableSet(WidgetT *widget, uint8_t enabled);
uint16_t widgetHeightGet(WidgetT *widget);
WidgetT *widgetInit(WidgetT *widget, uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t marginX, uint16_t marginY, uint16_t marginX2, uint16_t marginY2);
uint16_t widgetMarginBottomGet(WidgetT *widget);
uint16_t widgetMarginLeftGet(WidgetT *widget);
uint16_t widgetMarginRightGet(WidgetT *widget);
uint16_t widgetMarginTopGet(WidgetT *widget);
WidgetT *widgetNew(uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t marginX, uint16_t marginY, uint16_t marginX2, uint16_t marginY2);
uint8_t widgetVisibleGet(WidgetT *widget);
void widgetVisibleSet(WidgetT *widget, uint8_t enabled);

View file

@ -443,6 +443,7 @@ static void processNetworkEvent(void) {
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT:
_connected = 0;
_modemCommandMode = 1;
comAddToBuffer("\13NO CARRIER\13", 12);
break;
default:

View file

@ -55,17 +55,16 @@ typedef struct PortS {
} PortT;
static WindowT *winDetecting;
static LabelT *lblOneMoment;
static WindowT *winSettings;
static FrameT *frmComPorts;
static FrameT *frmServer;
static ButtonT *btnOkay;
static TextboxT *txtServer;
static UpdownT *updPort;
static PortT port[4];
static WindowT *winDetecting;
static LabelT *lblOneMoment;
static WindowT *winSettings;
static FrameT *frmComPorts;
static FrameT *frmServer;
static ButtonT *btnOkay;
static TextboxT *txtServer;
static UpdownT *updPort;
static PortT port[4];
static widgetCallback done;
static void btnOkayClick(WidgetT *widget);
@ -90,9 +89,9 @@ static void btnOkayClick(WidgetT *widget) {
_configData.serverHost = strdup(textboxValueGet(txtServer));
_configData.serverPort = updownValueGet(updPort);
// Return to welcome dialog.
taskCreate(taskWelcome, NULL);
// Return to calling routine.
guiDelete(D(winSettings));
done(NULL);
}
@ -101,10 +100,9 @@ void taskSettings(void *data) {
int32_t rc;
uint32_t len;
char buffer[1024];
uint8_t quarterSeconds = 0;
uint8_t selected = 1;
(void)data;
done = (widgetCallback)data;
TagItemT uiDetecting[] = {
T_START,
@ -126,15 +124,10 @@ void taskSettings(void *data) {
for (int x=0; x<4; x++) {
rc = comOpen(x, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS);
if (rc == SER_SUCCESS) {
snprintf(buffer, 1024, "%s%c", "AT+SOCK1", 13);
snprintf(buffer, 1023, "%s%c", "AT+SOCK1", 13);
comWrite(x, buffer, strlen(buffer));
// Wait a second.
quarterSeconds = 0;
while (quarterSeconds < 5) {
taskYield();
if (timerQuarterSecondTick) quarterSeconds++;
}
len = comRead(x, buffer, 1024);
// timerQuarterSecondsWait(4);
len = comRead(x, buffer, 1023);
buffer[len] = 0;
if (strstr(buffer, "OK")) {
snprintf(port[x].title, TITLE_LEN - 1, "COM%d - SoftModem Found!", x + 1);

View file

@ -0,0 +1,80 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "comport.h"
#include "timer.h"
#include "task.h"
int comReceiveBufferFlush(int com) {
char buffer[256];
int result = 1;
while (result > 0) {
result = comRead(com, buffer, 255);
}
return result;
}
int comWaitWithTimeout(int com, char *buffer, int len, int quarterSeconds, char *expecting) {
int r;
int quarterTicks = 0;
int count = 0;
int bufferIndex = 0;
char data[2];
while (quarterTicks <= quarterSeconds) {
r = comRead(com, data, 1);
if (r == 1) {
logWrite("Byte\n");
buffer[bufferIndex++] = data[0];
buffer[bufferIndex] = 0;
if (data[0] == expecting[count]) {
logWrite("Expect\n");
count++;
if (count == (int)strlen(expecting)) {
// Found our expect.
break;
}
} else {
count = 0;
}
if (bufferIndex == len - 1) {
// Out of buffer.
break;
}
} else {
sprintf(data, "%c", 0);
}
if (_timerQuarterSecondTick) {
quarterTicks++;
logWrite("Tick\n");
}
taskYield();
}
if (count == (int)strlen(expecting)) {
return bufferIndex;
}
return -bufferIndex;
}

View file

@ -52,4 +52,8 @@ int comWrite(int com, const char *data, int len);
#endif
int comReceiveBufferFlush(int com);
int comWaitWithTimeout(int com, char *buffer, int len, int quarterSeconds, char *expecting);
#endif // COMPORT_H

View file

@ -65,6 +65,7 @@ long biostime(int cmd, long newtime);
// Now our headers.
#include "log.h"
#include "util.h"
// Allocation helpers.

View file

@ -23,9 +23,8 @@
//#define MCO_DEFAULT_STACK_SIZE 114688 // Default is 57344
#include "thirdparty/minicoro/minicoro.h"
#include "array.h"
#include "task.h"
#include "array.h"
typedef struct TaskS {
@ -111,6 +110,6 @@ void taskStartup(void) {
}
void taskYield(void) {
void __attribute__ ((noinline)) taskYield(void) {
mco_yield(mco_running());
}

View file

@ -19,6 +19,8 @@
#include "timer.h"
#include "task.h"
#include "gui.h"
#define SECONDS_IN_DAY 86400
@ -26,18 +28,18 @@
#define TICKS_PER_DAY (SECONDS_IN_DAY * TICKS_PER_SECOND)
uint8_t timerQuarterSecondTick = 0;
uint8_t timerHalfSecondTick = 0;
uint8_t timerSecondTick = 0;
volatile uint8_t _timerQuarterSecondTick = 0;
volatile uint8_t _timerHalfSecondTick = 0;
volatile uint8_t _timerSecondTick = 0;
uint8_t timerQuarterSecondOn = 0;
uint8_t timerHalfSecondOn = 0;
uint8_t timerSecondOn = 0;
volatile uint8_t _timerQuarterSecondOn = 0;
volatile uint8_t _timerHalfSecondOn = 0;
volatile uint8_t _timerSecondOn = 0;
static long _timerLast = 0;
static uint8_t _timerHalfSecond = 2;
static uint8_t _timerSecond = 2;
static volatile long timerLast = 0;
static volatile uint8_t timerHalfSecond = 2;
static volatile uint8_t timerSecond = 2;
void timerShutdown(void) {
@ -46,7 +48,7 @@ void timerShutdown(void) {
void timerStartup(void) {
_timerLast = biostime(0, 0);
timerLast = biostime(0, 0);
}
@ -57,40 +59,55 @@ void timerUpdate(void) {
now = biostime(0, 0);
// Reset ticks.
timerQuarterSecondTick = 0;
timerHalfSecondTick = 0;
timerSecondTick = 0;
_timerQuarterSecondTick = 0;
_timerHalfSecondTick = 0;
_timerSecondTick = 0;
// Ensure we haven't rolled past midnight between calls.
if (now >= _timerLast) {
delta = now - _timerLast;
if (now >= timerLast) {
delta = now - timerLast;
} else {
// Compensate for midnight rollover.
delta = (now + TICKS_PER_DAY) - _timerLast;
delta = (now + TICKS_PER_DAY) - timerLast;
}
// Everything ticks off the quarter second.
if (delta > TICKS_PER_SECOND * 0.25) {
_timerLast = now;
timerLast = now;
// Quarter Second timer.
timerQuarterSecondOn = !timerQuarterSecondOn;
timerQuarterSecondTick = 1;
_timerQuarterSecondOn = !_timerQuarterSecondOn;
_timerQuarterSecondTick = 1;
// Half Second timer.
if (--_timerHalfSecond == 0) {
_timerHalfSecond = 2;
timerHalfSecondOn = !timerHalfSecondOn;
timerHalfSecondTick = 1;
if (--timerHalfSecond == 0) {
timerHalfSecond = 2;
_timerHalfSecondOn = !_timerHalfSecondOn;
_timerHalfSecondTick = 1;
// Second timer
if (--_timerSecond == 0) {
_timerSecond = 2;
timerSecondOn = !timerSecondOn;
timerSecondTick = 1;
if (--timerSecond == 0) {
timerSecond = 2;
_timerSecondOn = !_timerSecondOn;
_timerSecondTick = 1;
} // Second.
} // Half Second.
} // Quarter Second.
}
/*
void timerQuarterSecondsWait(u_int8_t quarterSeconds) {
uint8_t counter = 0;
while (counter <= quarterSeconds && !guiHasStopped()) {
if (_timerQuarterSecondTick) {
counter++;
}
logWrite("Waiting %d of %d\n", counter, quarterSeconds);
taskYield();
}
}
*/

View file

@ -25,18 +25,19 @@
#include "os.h"
extern uint8_t timerQuarterSecondTick;
extern uint8_t timerHalfSecondTick;
extern uint8_t timerSecondTick;
extern volatile uint8_t _timerQuarterSecondTick;
extern volatile uint8_t _timerHalfSecondTick;
extern volatile uint8_t _timerSecondTick;
extern uint8_t timerQuarterSecondOn;
extern uint8_t timerHalfSecondOn;
extern uint8_t timerSecondOn;
extern volatile uint8_t _timerQuarterSecondOn;
extern volatile uint8_t _timerHalfSecondOn;
extern volatile uint8_t _timerSecondOn;
void timerShutdown(void);
void timerStartup(void);
void timerUpdate(void);
//void timerQuarterSecondsWait(u_int8_t quarterSeconds);
#endif // TIMER_H

View file

@ -24,40 +24,175 @@
#include "taglist.h"
#include "task.h"
#include "config.h"
#include "comport.h"
#include "timer.h"
#include "window.h"
#include "picture.h"
#include "button.h"
#include "msgbox.h"
static WindowT *winWelcome = NULL;
static PictureT *picLogo = NULL;
static PictureT *picInit = NULL;
static PictureT *picDialing = NULL;
static PictureT *picConnect = NULL;
static ButtonT *btnQuit = NULL;
static ButtonT *btnSettings = NULL;
static ButtonT *btnConnect = NULL;
static void btnConnectClick(WidgetT *widget);
static void btnMsgBox(MsgBoxButtonT button);
static void btnMsgBoxQuit(MsgBoxButtonT button);
static void btnQuitClick(WidgetT *widget);
static void btnSettingsClick(WidgetT *widget);
static void setButtons(uint8_t enabled);
static void settingsFinished(WidgetT *widget);
static void btnMsgBox(MsgBoxButtonT button) {
(void)button;
// Re-enable buttons.
setButtons(1);
// Reset to Welcome image.
widgetVisibleSet(W(picLogo), 1);
widgetVisibleSet(W(picInit), 0);
widgetVisibleSet(W(picDialing), 0);
widgetVisibleSet(W(picConnect), 0);
}
static void btnMsgBoxQuit(MsgBoxButtonT button) {
if (button == MSGBOX_BUTTON_ONE) {
guiStop();
} else {
setButtons(1);
}
}
static void btnConnectClick(WidgetT *widget) {
uint32_t r;
uint32_t len;
char buffer[1024];
int8_t timeout = 7 * 4; // Seven seconds (of quarter seconds) to connect to server.
uint16_t count = 0;
uint8_t connected = 0;
char *banner = "KPMPGSMKII";
(void)widget;
// Ghost all buttons.
widgetEnableSet(W(btnConnect), 0);
widgetEnableSet(W(btnSettings), 0);
widgetEnableSet(W(btnQuit), 0);
// Hide welcome banner, show init.
widgetVisibleSet(W(picLogo), 0);
widgetVisibleSet(W(picInit), 1);
taskYield();
// Open COM port.
r = comOpen(_configData.serialCom - 1, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS);
if (r != SER_SUCCESS) {
msgBoxOne("COM Problem", MSGBOX_ICON_ERROR, "Unable to open COM port!\nPlease check settings.", "Okay", btnMsgBox);
return;
}
logWrite("COM open\n");
// Send a CR to clear anything in the modem.
snprintf(buffer, 1023, "%c", 13);
comWrite(_configData.serialCom - 1, buffer, strlen(buffer));
logWrite("CR sent\n");
// Wait roughly a second.
comWaitWithTimeout(_configData.serialCom - 1, buffer, 1023, 4, "weExpectNothing");
//uint32_t dumbThing = timerQuarterSecondsWait(4);
logWrite("Wait over\n");
// Flush COM port.
comReceiveBufferFlush(_configData.serialCom - 1);
logWrite("Port flushed\n");
// Send actual init
snprintf(buffer, 1023, "%s%c", "AT+SOCK1", 13);
comWrite(_configData.serialCom - 1, buffer, strlen(buffer));
// Wait roughly a second.
// timerQuarterSecondsWait(4);
// Read COM port & check for OK.
len = comRead(_configData.serialCom - 1, buffer, 1023);
buffer[len] = 0;
if (!strstr(buffer, "OK")) {
comClose(_configData.serialCom - 1);
msgBoxOne("Modem Problem", MSGBOX_ICON_ERROR, "Modem does not support ENET!\nPlease check settings.", "Okay", btnMsgBox);
return;
}
// Show dialing, dial service.
widgetVisibleSet(W(picDialing), 1);
taskYield();
snprintf(buffer, 1023, "ATDT%s:%d%c", _configData.serverHost, _configData.serverPort, 13);
comWrite(_configData.serialCom - 1, buffer, strlen(buffer));
while (timeout > 0 && connected == 0) {
len = comRead(_configData.serialCom - 1, buffer, 1);
// Did we get a character?
if (len == 1) {
// Is it the next we expect in the server banner?
if (buffer[0] == banner[count]) {
count++;
} else {
count = 0;
}
// Are we connected?
if (count == strlen(banner)) {
connected = 1;
}
}
// Tick timeout.
if (_timerQuarterSecondTick) timeout--;
taskYield();
}
// timerQuarterSecondsWait(4);
comReceiveBufferFlush(_configData.serialCom - 1);
// Did we connect?
if (!connected) {
comClose(_configData.serialCom - 1);
msgBoxOne("No Connection", MSGBOX_ICON_INFORMATION, "Unable to connect to server!\nPlease check settings or try later.", "Okay", btnMsgBox);
return;
}
// Connected! Show icon and negotiate session.
widgetVisibleSet(W(picConnect), 1);
taskYield();
}
static void btnQuitClick(WidgetT *widget) {
(void)widget;
guiStop();
setButtons(0);
msgBoxTwo("Quit?", MSGBOX_ICON_QUESTION, "Exit to DOS?", "Okay", btnMsgBoxQuit, "Cancel", btnMsgBoxQuit);
}
static void btnSettingsClick(WidgetT *widget) {
(void)widget;
taskCreate(taskSettings, NULL);
guiDelete(D(winWelcome));
setButtons(0);
taskCreate(taskSettings, settingsFinished);
}
void setButtons(uint8_t enabled) {
widgetEnableSet(W(btnConnect), (_configData.serialCom > 0 && strlen(_configData.serverHost) > 2) ? enabled : 0);
widgetEnableSet(W(btnSettings), enabled);
widgetEnableSet(W(btnQuit), enabled);
}
static void settingsFinished(WidgetT *widget) {
(void)widget;
setButtons(1);
}
@ -72,10 +207,28 @@ void taskWelcome(void *data) {
T_WINDOW, O(winWelcome),
T_TITLE, P("Welcome to KangaWorld!"),
T_WIDTH, 500, T_HEIGHT, 225,
T_PICTURE, O(picLogo),
T_FILENAME, P("data/logo.png"),
T_X, 18, T_Y, 18,
T_PICTURE, T_DONE,
T_PICTURE, O(picInit),
T_FILENAME, P("data/dinit.png"),
T_X, 18, T_Y, 18,
T_VISIBLE, T_FALSE,
T_PICTURE, T_DONE,
T_PICTURE, O(picDialing),
T_FILENAME, P("data/ddialing.png"),
T_X, 179, T_Y, 18,
T_VISIBLE, T_FALSE,
T_PICTURE, T_DONE,
T_PICTURE, O(picConnect),
T_FILENAME, P("data/dconnect.png"),
T_X, 339, T_Y, 18,
T_VISIBLE, T_FALSE,
T_PICTURE, T_DONE,
T_BUTTON, O(btnQuit),
T_TITLE, P("Quit"),
T_X, 30, T_Y, 157,
@ -92,6 +245,7 @@ void taskWelcome(void *data) {
T_CLICK, P(btnConnectClick),
T_ENABLED, (_configData.serialCom > 0 && strlen(_configData.serverHost) > 2) ? T_TRUE : T_FALSE,
T_BUTTON, T_DONE,
T_WINDOW, T_DONE,
T_END
};

View file

@ -62,3 +62,34 @@ void utilDie(const char *why, ...) {
logWrite("DIE: %s", msg);
exit(1);
}
char *utilCreateString(char *format, ...) {
va_list args;
char *string;
va_start(args, format);
string = utilCreateStringVArgs(format, args);
va_end(args);
return string;
}
__attribute__((__format__(__printf__, 1, 0)))
char *utilCreateStringVArgs(char *format, va_list args) {
va_list argsCopy;
int32_t size = 0;
char *buffer = NULL;
va_copy(argsCopy, args);
size = vsnprintf(NULL, 0, format, argsCopy) + 1;
va_end(argsCopy);
buffer = calloc(1, (size_t)size);
if (buffer) {
vsnprintf(buffer, (size_t)size, format, args);
}
return buffer;
}

View file

@ -27,6 +27,8 @@
char *utilAppNameWithNewExtensionGet(char *appName, char *extension);
void utilDie(const char *why, ...);
char *utilCreateString(char *format, ...);
char *utilCreateStringVArgs(char *format, va_list args);
#endif // UTIL_H