blob: fa85a40f87cd1eeda42f174cba9ea342a50eb952 [file] [log] [blame]
#include "contiki.h"
#include "socket.h"
#include "ctk-draw.h"
#include <cbm.h>
#include <c64.h>
#include <string.h>
static struct {
struct socket sout, sin;
struct pt inpt, outpt;
char outputbuf[200];
char inputbuf[200];
unsigned short len;
} s;
#define CURSOR_ON() *(char *)0xcc = 0
#define CURSOR_OFF() *(char *)0xcc = 1
static void ctkmode(void);
/*---------------------------------------------------------------------------*/
static
PT_THREAD(send(void))
{
SOCKET_BEGIN(&s.sout);
SOCKET_SEND(&s.sout, s.outputbuf, s.len);
SOCKET_END(&s.sout);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(handle_output(void))
{
ctk_arch_key_t c;
char *ptr;
PT_BEGIN(&s.outpt);
while(1) {
PT_WAIT_UNTIL(&s.outpt, (ctk_mode_get() == CTK_MODE_EXTERNAL) &&
kbhit());
ptr = s.outputbuf;
s.len = 0;
while(kbhit() && s.len < sizeof(s.outputbuf)) {
c = cgetc();
*ptr = c;
++ptr;
++s.len;
}
PT_WAIT_THREAD(&s.outpt, send());
}
PT_END(&s.outpt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(handle_input(void))
{
unsigned short i;
char *ptr;
char next;
next = 1;
PT_BEGIN(&s.inpt);
while(1) {
/* Wait until data arrives. */
next = 0;
PT_WAIT_UNTIL(&s.inpt, next && uip_newdata());
CURSOR_OFF();
/* Print it out on the screen. */
ptr = (char *)uip_appdata;
for(i = 0; i < uip_len; ++i) {
cbm_k_bsout(*ptr);
++ptr;
}
CURSOR_ON();
}
PT_END(&s.inpt);
}
/*---------------------------------------------------------------------------*/
static void
appcall(void *state)
{
if(uip_closed() || uip_aborted() || uip_timedout()) {
ctkmode();
} else if(uip_connected()) {
} else {
handle_input();
handle_output();
}
}
/*---------------------------------------------------------------------------*/
static struct uip_conn *
connect(u16_t *host, u16_t port)
{
SOCKET_INIT(&s.sin, s.inputbuf, sizeof(s.inputbuf));
SOCKET_INIT(&s.sout, s.inputbuf, sizeof(s.inputbuf));
PT_INIT(&s.inpt);
PT_INIT(&s.outpt);
return tcp_connect(host, htons(port), NULL);
}
/*---------------------------------------------------------------------------*/
EK_POLLHANDLER(pollhandler);
EK_EVENTHANDLER(eventhandler, ev, data);
EK_PROCESS(p, "C/G terminal", EK_PRIO_NORMAL,
eventhandler, pollhandler, NULL);
static ek_id_t id = EK_ID_NONE;
static struct uip_conn *conn;
static u16_t serveraddr[2];
static u16_t serverport;
/*---------------------------------------------------------------------------*/
static struct ctk_window window;
static struct ctk_label hostlabel =
{CTK_LABEL(0, 0, 4, 1, "Host")};
static char host[32];
static struct ctk_textentry hostentry =
{CTK_TEXTENTRY(5, 0, 20, 1, host, sizeof(host) - 1)};
static struct ctk_label portlabel =
{CTK_LABEL(27, 0, 4, 1, "Port")};
static char port[7];
static struct ctk_textentry portentry =
{CTK_TEXTENTRY(32, 0, 4, 1, port, sizeof(port) - 1)};
static struct ctk_button connectbutton =
{CTK_BUTTON(0, 2, 7, "Connect")};
static struct ctk_button switchbutton =
{CTK_BUTTON(30, 2, 6, "Switch")};
static struct ctk_label helplabel =
{CTK_LABEL(0, 4, 37, 1, "RUN/STOP to return from terminal view")};
/*---------------------------------------------------------------------------*/
LOADER_INIT_FUNC(cgterm_init, arg)
{
arg_free(arg);
if(id == EK_ID_NONE) {
id = ek_start(&p);
}
}
/*---------------------------------------------------------------------------*/
static void
ctkmode(void)
{
ctk_mode_set(CTK_MODE_NORMAL);
ctk_draw_init();
ctk_desktop_redraw(NULL);
}
/*---------------------------------------------------------------------------*/
static void
textmode(void)
{
ctk_mode_set(CTK_MODE_EXTERNAL);
VIC.ctrl1 = 0x1b; /* $D011 */
VIC.addr = 0x17; /* $D018 */
VIC.ctrl2 = 0xc8; /* $D016 */
CIA2.pra = 0x03; /* $DD00 */
VIC.bordercolor = 0x00; /* $D020 */
VIC.bgcolor0 = 0x00; /* $D021 */
CURSOR_ON();
}
/*---------------------------------------------------------------------------*/
EK_EVENTHANDLER(eventhandler, ev, data)
{
u16_t *ipaddr;
char *cptr;
if(ev == tcpip_event) {
appcall(data);
} else if(ev == EK_EVENT_INIT) {
ctk_window_new(&window, 38, 5, "C/G term");
CTK_WIDGET_ADD(&window, &hostlabel);
CTK_WIDGET_ADD(&window, &hostentry);
CTK_WIDGET_ADD(&window, &portlabel);
CTK_WIDGET_ADD(&window, &portentry);
CTK_WIDGET_ADD(&window, &connectbutton);
CTK_WIDGET_ADD(&window, &switchbutton);
CTK_WIDGET_ADD(&window, &helplabel);
ctk_window_open(&window);
} else if(ev == ctk_signal_widget_activate) {
if(data == (ek_data_t)&switchbutton) {
textmode();
} else if(data == (ek_data_t)&connectbutton) {
serverport = 0;
for(cptr = port; *cptr != ' ' && *cptr != 0; ++cptr) {
if(*cptr < '0' || *cptr > '9') {
return;
}
serverport = 10 * serverport + *cptr - '0';
}
ipaddr = serveraddr;
if(uiplib_ipaddrconv(host, (u8_t *)serveraddr) == 0) {
ipaddr = resolv_lookup(host);
if(ipaddr == NULL) {
resolv_query(host);
} else {
uip_ipaddr_copy(serveraddr, ipaddr);
}
}
if(ipaddr != NULL) {
conn = connect(serveraddr, serverport);
if(conn != NULL) {
memset((char *)0x0400, 0x20, 40*25);
memset((char *)0xd800, 0x01, 40*25);
textmode();
}
}
}
} else if(ev == resolv_event_found) {
ipaddr = resolv_lookup(host);
if(ipaddr != NULL) {
uip_ipaddr_copy(serveraddr, ipaddr);
conn = connect(serveraddr, serverport);
if(conn != NULL) {
memset((char *)0x0400, 0x20, 40*25);
memset((char *)0xd800, 0x01, 40*25);
textmode();
}
}
} else if(ev == EK_EVENT_REQUEST_EXIT ||
ev == ctk_signal_window_close) {
ctk_window_close(&window);
ek_exit();
LOADER_UNLOAD();
}
}
/*---------------------------------------------------------------------------*/
EK_POLLHANDLER(pollhandler)
{
if(ctk_mode_get() == CTK_MODE_EXTERNAL) {
if(CIA1.prb == 0x7f) {
ctkmode();
} else if(kbhit() && conn != NULL) {
tcpip_poll_tcp(conn);
}
}
}
/*---------------------------------------------------------------------------*/