ScriptedAmigaEmulator/sae/serial.js
Rupert Hausberger fbf36a4fa5 update 0.9.0
2016-07-15 19:44:16 +02:00

302 lines
7.3 KiB
JavaScript

/*-------------------------------------------------------------------------
| SAE - Scripted Amiga Emulator
| https://github.com/naTmeg/ScriptedAmigaEmulator
|
| Copyright (C) 2012-2016 Rupert Hausberger
|
| 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 2
| 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.
|
| Note: ported from WinUAE 3.2.x
-------------------------------------------------------------------------*/
function SAEO_Serial() {
const WARN_SERIAL = true;
const DEBUG_SERIAL = 0; /* 0,1,2,3 */
var inbuf = new Uint8Array(1024);
var outbuf = new Uint8Array(1024);
var inptr = 0, inlast = 0, outlast = 0;
var waitqueue = false;
var dsr = false;
var dtr = false;
//var carrier = false;
var notify = false;
var serdev = false;
var serper = 0, serdat = 0;
/*---------------------------------*/
function open() { //serial_open()
if (serdev)
return;
/*if ((sd = open(currprefs.sername, O_RDWR|O_NONBLOCK|O_BINARY, 0)) < 0) {
SAEF_log("serial.open() Could not open Device %s", currprefs.sername);
return;
}
serdev = true;
if (tcgetattr (sd, &tios) < 0) {
SAEF_log("serial.open() TCGETATTR failed");
return;
}
cfmakeraw(&tios);
#ifndef MODEMTEST
tios.c_cflag &= ~CRTSCTS;
#else
tios.c_cflag |= CRTSCTS;
#endif
if (tcsetattr (sd, TCSADRAIN, &tios) < 0)
SAEF_log("serial.open() TCSETATTR failed");*/
}
function close() { //serial_close()
//if (sd >= 0) close(sd);
serdev = false;
}
/*---------------------------------*/
function read_buffer() {
if (inptr < inlast)
return inbuf[inptr++];
/*if (serdev) {
inlast = read(sd, inbuf, 1024);
inptr = 0;
if (inptr < inlast)
return inbuf[inptr++];
}*/
return false;
}
function flush_buffer() {
if (outlast > 0) { //OWN
var str = "";
for (var i = 0; i < outlast; i++)
str += String.fromCharCode(outbuf[i]);
//SAEF_info(str);
console.log(str);
}
if (serdev) {
/*if (outlast) {
if (sd != 0)
write(sd, outbuf, outlast);
}*/
outlast = 0;
} else {
outlast = 0;
inptr = 0;
inlast = 0;
}
}
/*---------------------------------*/
this.SERPER = function(w) {
var baud, pspeed;
if (!SAEV_config.serial.enabled)
return;
if (serper == w) /* don't set baudrate if it's already ok */
return;
serper = w;
if (WARN_SERIAL && (w & 0x8000)) SAEF_warn("serial.SERPER() 9bit transmission not implemented.");
switch (w & 0x7fff) {
case 0x2e9b:
case 0x2e14: baud = 300; pspeed = 300; break;
case 0x170a:
case 0x0b85: baud = 1200; pspeed = 1200; break;
case 0x05c2:
case 0x05b9: baud = 2400; pspeed = 2400; break;
case 0x02e9:
case 0x02e1: baud = 4800; pspeed = 4800; break;
case 0x0174:
case 0x0170: baud = 9600; pspeed = 9600; break;
case 0x00b9:
case 0x00b8: baud = 19200; pspeed = 19200; break;
case 0x005c:
case 0x005d: baud = 38400; pspeed = 38400; break;
case 0x003d: baud = 57600; pspeed = 57600; break;
case 0x001e: baud = 115200; pspeed = 115200; break;
case 0x000f: baud = 230400; pspeed = 230400; break;
default: {
if (WARN_SERIAL) SAEF_warn("serial.SERPER() unsupported baudrate (0x%04x) %d", w & 0x7fff, ~~(3579546.471 / ((w & 0x7fff) + 1)));
return;
}
}
if (serdev) {
/*if (tcgetattr(sd, &tios) < 0) {
if (WARN_SERIAL) SAEF_warn("serial.SERPER() TCGETATTR failed");
return;
}
if (cfsetispeed(&tios, pspeed) < 0) {
if (WARN_SERIAL) SAEF_warn("serial.SERPER() CFSETISPEED (%d bps) failed", baud);
return;
}
if (cfsetospeed(&tios, pspeed) < 0) {
if (WARN_SERIAL) SAEF_warn("serial.SERPER() CFSETOSPEED (%d bps) failed", baud);
return;
}
if (tcsetattr(sd, TCSADRAIN, &tios) < 0) {
if (WARN_SERIAL) SAEF_warn("serial.SERPER() TCSETATTR failed");
return;
}*/
}
if (DEBUG_SERIAL > 0) SAEF_log("serial.SERPER() baudrate set to %d bit/sec", baud);
}
this.SERDAT = function(w) {
if (!SAEV_config.serial.enabled)
return;
var z = w & 0xff;
if (SAEV_config.serial.demand && !dtr) {
if (!notify) {
if (WARN_SERIAL) SAEF_warn("serial.SERDAT() Your software needs SERIAL ALWAYS to work properly. (disable 'serial.demand' in the config)");
notify = true;
}
return;
} else {
outbuf[outlast++] = z;
if (outlast == outbuf.length)
flush_buffer();
}
if (DEBUG_SERIAL > 2) SAEF_log("serial.SERDAT() wrote 0x%04x", w);
serdat |= 0x2000; /* Set TBE in the SERDATR ... */
SAEV_Custom_intreq |= SAEC_Custom_INTF_TBE; /* ... and in INTREQ register */
return;
}
this.SERDATR = function() {
if (!SAEV_config.serial.enabled)
return 0x2000;
if (DEBUG_SERIAL > 2) SAEF_log("serial.SERDATR() read 0x%04x", serdat);
waitqueue = false;
return serdat;
}
this.SERDATS = function() {
if (!serdev) /* || (serdat & 0x4000)) */
return 0;
if (waitqueue) {
SAEV_Custom_intreq |= SAEC_Custom_INTF_RBF;
return 1;
}
var z;
if ((z = read_buffer()) !== false) {
waitqueue = true;
serdat = 0x4100; /* RBF and STP set! */
serdat |= (z & 0xff);
SAEV_Custom_intreq |= SAEC_Custom_INTF_RBF; /* Set RBF flag (Receive Buffer full) */
if (DEBUG_SERIAL > 1) SAEF_log("serial.SERDATS() received 0x%02x --> serdat 0x%04x", z, serdat);
return 1;
}
return 0;
}
/*---------------------------------*/
this.dtr_on = function() {
if (DEBUG_SERIAL > 0) SAEF_log("serial.dtr_on()");
dtr = true;
if (SAEV_config.serial.demand)
open();
}
this.dtr_off = function() {
if (DEBUG_SERIAL > 0) SAEF_log("serial.dtr_off()");
dtr = false;
if (SAEV_config.serial.demand)
close();
}
this.readstatus = function(ignored) {
var status = 0;
/*ioctl (sd, TIOCMGET, &status);
if (status & TIOCM_CAR) {
if (!carrier) {
ciabpra |= 0x20;
carrier = true;
if (DEBUG_SERIAL > 0) SAEF_log("serial.readstatus() Carrier detect");
}
} else {
if (carrier) {
ciabpra &= ~0x20;
carrier = false;
if (DEBUG_SERIAL > 0) SAEF_log("serial.readstatus() Carrier lost");
}
}
if (status & TIOCM_DSR) {
if (!dsr) {
ciabpra |= 0x08;
dsr = true;
}
} else {
if (dsr) {
ciabpra &= ~0x08;
dsr = false;
}
}*/
return status;
}
this.writestatus = function(old, nw) {
if ((old & 0x80) == 0x80 && (nw & 0x80) == 0x00) this.dtr_on();
if ((old & 0x80) == 0x00 && (nw & 0x80) == 0x80) this.dtr_off();
if (DEBUG_SERIAL > 0) {
if ((old & 0x40) != (nw & 0x40)) SAEF_log("serial.writestatus() RTS %s", ((nw & 0x40) == 0x40) ? "set" : "cleared");
if ((old & 0x10) != (nw & 0x10)) SAEF_log("serial.writestatus() CTS %s", ((nw & 0x10) == 0x10) ? "set" : "cleared");
}
return nw;
}
/*---------------------------------*/
this.setup = function() { //serial_init()
if (!SAEV_config.serial.enabled)
return;
if (!SAEV_config.serial.demand)
open();
serdat = 0x2000;
}
this.cleanup = function() { //serial_exit()
close();
dtr = false;
}
this.reset = function() {
inptr = 0, inlast = 0, outlast = 0
waitqueue = false;
dsr = false;
dtr = false;
//carrier = false;
notify = false;
serper = 0;
serdat = 0x2000;
};
}