|
Post by atolle on Mar 7, 2006 0:57:39 GMT -5
I fixed the ACIA core in WinVICE so it will work up to 38400 bps now with tcpser4j (works in Novaterm at least).
Here are the major problems I found:
1) It would connect and disconnect multiple times from the tcp port very quickly. This would have the effect of resetting the connecton. I basically forced it to open the connection once and leave it there.
2) It had the wrong timer settings: was calculating the delay based on bits per second instead of bytes per second.
3) It was clearing the received bytes before they could be read.
4) It was forcing the DCD line to low which is a problem with some programs. I have it set to force the DCD line high now, but this still needs to be addressed because BBS programs depend on the DCD setting. Any suggestions? I was thinking of some sort of out-of-band data. Winsock supports that... I would just need to modify tcpser4j to send the OOB signals.
There is just one file to change in the source: aciacore.c I need to post it somewhere for download. Perhaps I will put a zip of it on my bbs. I'll keep everyone informed.
I can put a compiled WinVice x64 executable up somewhere too if anyone wants it.
|
|
|
Post by atolle on Mar 7, 2006 4:47:38 GMT -5
I'm just gonna append the source file to this message... Replace the text in the existing aciacore.c with it and recompile VICE. Notes: 1) You need to have the tcpser4j application running and listening before you start the x64 machine. In the config for tcpser4j, change the modem device entry to something like the following: Modem type="ip232" device="25232" The type must equal "ip232". In this example, it will make it listen on port 25232 for VICE to use as its modem. Note that this is different from the Line Port setting. 2) Configure one of the RS-232 ports in VICE to refer to your local machine and port where tcpser4j is listening. I.e. if tcpser4j is listening on port 25232, you could use something like: 127.0.0.1:25232 3) Enable the ACIA adapter in WinVICE and select the RS-232 device you configured in step 2. Note that NMI mode is the standard setting for the ACIA. 4) Start up a terminal in WinVICE that is SwiftLink compatible. I've tested Novaterm 9.6 and it appears to work great. //======================================================= /* * aciacore.c - Template file for ACIA 6551 emulation. * * Written by * André Fachat <fachat@physik.tu-chemnitz.de> * * This file is part of VICE, the Versatile Commodore Emulator. * See README for copyright notice. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. * */
#include "vice.h"
#include <stdio.h>
#include "acia.h" #include "alarm.h" #include "clkguard.h" #include "cmdline.h" #include "interrupt.h" #include "log.h" #include "machine.h" #include "resources.h" #include "rs232drv.h" #include "snapshot.h" #ifdef HAS_TRANSLATION #include "translate.h" #endif #include "types.h"
#undef DEBUG
static alarm_t *acia_alarm = NULL;
static unsigned int acia_int_num;
static int acia_ticks = 21111; /* number of clock ticks per char */ static int fd = -1; //static int intx = 0; /* indicates that a transmit is currently ongoing */ static int irq = 0; static BYTE cmd; static BYTE ctrl; static BYTE rxdata; /* data that has been received last */ static BYTE txdata; /* data prepared to send */ static BYTE status; static int alarm_active = 0; /* if alarm is set or not */
static log_t acia_log = LOG_ERR;
static void int_acia(CLOCK offset, void *data);
static BYTE acia_last_read = 0; /* the byte read the last time (for RMW) */
/******************************************************************/
static CLOCK acia_alarm_clk = 0;
static int acia_device; static int acia_irq = IK_NONE; static int acia_irq_res;
static int acia_set_device(resource_value_t v, void *param) {
if (fd >= 0) { log_error(acia_log, "Device open, change effective only after close!"); }
acia_device = (int)v; return 0; }
static void acia_set_int(int aciairq, unsigned int int_num, int value) { if (aciairq == IK_IRQ) mycpu_set_irq(int_num, value); if (aciairq == IK_NMI) mycpu_set_nmi(int_num, value); }
static int acia_set_irq(resource_value_t v, void *param) { int new_irq_res = (int)v; int new_irq; static const int irq_tab[] = { IK_NONE, IK_IRQ, IK_NMI };
if (new_irq_res < 0 || new_irq_res > 2) return -1;
new_irq = irq_tab[new_irq_res];
if (acia_irq != new_irq) { acia_set_int(acia_irq, acia_int_num, IK_NONE); if (irq) { acia_set_int(new_irq, acia_int_num, new_irq); } } acia_irq = new_irq; acia_irq_res = new_irq_res;
return 0; }
static const resource_t resources[] = { { MYACIA "Dev", RES_INTEGER, (resource_value_t)MyDevice, (void *)&acia_device, acia_set_device, NULL }, { MYACIA "Irq", RES_INTEGER, (resource_value_t)MyIrq, (void *)&acia_irq_res, acia_set_irq, NULL }, { NULL } };
int myacia_init_resources(void) { return resources_register(resources); }
#ifdef HAS_TRANSLATION static const cmdline_option_t cmdline_options[] = { { "-myaciadev", SET_RESOURCE, 1, NULL, NULL, MYACIA "Dev", NULL, IDCLS_P_0_3, IDCLS_SPECIFY_ACIA_RS232_DEVICE }, { NULL } }; #else static const cmdline_option_t cmdline_options[] = { { "-myaciadev", SET_RESOURCE, 1, NULL, NULL, MYACIA "Dev", NULL, "<0-3>", N_("Specify RS232 device this ACIA should work on") }, { NULL } }; #endif
int myacia_init_cmdline_options(void) { return cmdline_register_options(cmdline_options); }
/******************************************************************/
/* note: the first value is bogus. It should be 16*external clock. */ static const double acia_baud_table[16] = { 300, 100, 150, 219.84, 269.16, 300, 600, 1200, 2400, 3600, 4800, 7200, 9600, 14400, 19200, 38400
};
/******************************************************************/
static void clk_overflow_callback(CLOCK sub, void *var) { if (alarm_active) acia_alarm_clk -= sub; }
void myacia_init(void) {
acia_int_num = interrupt_cpu_status_int_new(maincpu_int_status, MYACIA);
acia_alarm = alarm_new(mycpu_alarm_context, MYACIA, int_acia, NULL);
clk_guard_add_callback(mycpu_clk_guard, clk_overflow_callback, NULL);
if (acia_log == LOG_ERR) acia_log = log_open(MYACIA);
#ifdef DEBUG log_message(acia_log, "myacia_init"); #endif
}
void myacia_reset(void) { #ifdef DEBUG log_message(acia_log, "reset_myacia"); #endif cmd = 0; ctrl = 0;
acia_ticks = (int)(machine_get_cycles_per_second() / (acia_baud_table[ctrl & 0xf] / 10));
status = 0x10; //intx = 0;
/* if (fd >= 0) rs232drv_close(fd); fd = -1; */
alarm_unset(acia_alarm); alarm_active = 0;
acia_set_int(acia_irq, acia_int_num, 0); irq = 0; }
/* -------------------------------------------------------------------------- */ /* The dump format has a module header and the data generated by the * chip... * * The version of this dump description is 0/0 */
#define ACIA_DUMP_VER_MAJOR 1 #define ACIA_DUMP_VER_MINOR 0
/* * The dump data: * * UBYTE TDR Transmit Data Register * UBYTE RDR Receiver Data Register * UBYTE SR Status Register (includes state of IRQ line) * UBYTE CMD Command Register * UBYTE CTRL Control Register * * UBYTE INTX 0 = no data to tx; 2 = TDR valid; 1 = in transmit * * DWORD TICKS ticks till the next TDR empty interrupt */
static const char module_name[] = MYACIA;
/* FIXME!!! Error check. */ /* FIXME!!! If no connection, emulate carrier lost or so */ int myacia_snapshot_write_module(snapshot_t *p) { snapshot_module_t *m;
m = snapshot_module_create(p, module_name, (BYTE)ACIA_DUMP_VER_MAJOR, (BYTE)ACIA_DUMP_VER_MINOR); if (m == NULL) return -1;
SMW_B(m, txdata); SMW_B(m, rxdata); SMW_B(m, (BYTE)(status | (irq?0x80:0))); SMW_B(m, cmd); SMW_B(m, ctrl); //SMW_B(m, (BYTE)(intx));
if (alarm_active) { SMW_DW(m, (acia_alarm_clk - myclk)); } else { SMW_DW(m, 0); }
snapshot_module_close(m);
return 0; }
int myacia_snapshot_read_module(snapshot_t *p) { BYTE vmajor, vminor; //BYTE byte; DWORD dword; snapshot_module_t *m;
alarm_unset(acia_alarm); /* just in case we don't find module */ alarm_active = 0;
mycpu_set_int_noclk(acia_int_num, 0);
m = snapshot_module_open(p, module_name, &vmajor, &vminor); if (m == NULL) return -1;
if (vmajor != ACIA_DUMP_VER_MAJOR) { snapshot_module_close(m); return -1; }
SMR_B(m, &txdata); SMR_B(m, &rxdata);
irq = 0; SMR_B(m, &status); if (status & 0x80) { status &= 0x7f; irq = 1; mycpu_set_int_noclk(acia_int_num, acia_irq); } else { mycpu_set_int_noclk(acia_int_num, 0); }
SMR_B(m, &cmd); if ((cmd & 1) && (fd < 0)) { fd = rs232drv_open(acia_device); } else if ((fd >= 0) && !(cmd & 1)) { rs232drv_close(fd); fd = -1; }
SMR_B(m, &ctrl); acia_ticks = (int)(machine_get_cycles_per_second() / (acia_baud_table[ctrl & 0xf] / 10));
//SMR_B(m, &byte); //intx = byte;
SMR_DW(m, &dword); if (dword) { acia_alarm_clk = myclk + dword; alarm_set(acia_alarm, acia_alarm_clk); alarm_active = 1; } else { alarm_unset(acia_alarm); alarm_active = 0; }
if (snapshot_module_close(m) < 0) return -1;
return 0; }
void REGPARM2 myacia_store(WORD a, BYTE b) {
#ifdef DEBUG log_message(acia_log, "store_myacia(%04x,%02x)", a, b); #endif
if (mycpu_rmw_flag) { myclk --; mycpu_rmw_flag = 0; myacia_store(a, acia_last_read); myclk ++; }
switch(a & 3) {
case ACIA_DR: if (cmd & 1) { if (status & 0x10) { txdata = b; status &= ~0x10; /* clr TDRE */ } } break;
case ACIA_SR: /* if (fd >= 0) rs232drv_close(fd); fd = -1; */ status &= ~0x04; cmd &= 0xe0; //intx = 0; acia_set_int(acia_irq, acia_int_num, 0); irq = 0; alarm_unset(acia_alarm); alarm_active = 0; break;
case ACIA_CTRL: ctrl = b; acia_ticks = (int)(machine_get_cycles_per_second() / (acia_baud_table[ctrl & 0xf] / 10)); if (cmd & 1) { acia_alarm_clk = myclk + acia_ticks; alarm_set(acia_alarm, acia_alarm_clk); alarm_active = 1; } break;
case ACIA_CMD: if (b & 1) { if (!(cmd & 1)) {
if (fd < 0) fd = rs232drv_open(acia_device);
acia_alarm_clk = myclk + acia_ticks; alarm_set(acia_alarm, acia_alarm_clk); alarm_active = 1; } } else { if (cmd & 1) { alarm_unset(acia_alarm); alarm_active = 0; } } cmd = b; break;
break; } }
BYTE REGPARM1 myacia_read(WORD a) { #ifdef DEBUG BYTE myacia_read_(WORD); BYTE b = myacia_read_(a); static WORD lasta = 0; static BYTE lastb = 0;
if ((a != lasta) || (b != lastb)) { log_message(acia_log, "read_myacia(%04x) -> %02x", a, b); } lasta = a; lastb = b; return b; } BYTE myacia_read_(WORD a) { #endif switch(a & 3) { case ACIA_DR: status &= ~0x08; acia_last_read = rxdata; return rxdata; case ACIA_SR: { BYTE c = status | (irq ? 0x80 : 0) | 0x40; acia_set_int(acia_irq, acia_int_num, 0); irq = 0; acia_last_read = c; return c; } case ACIA_CTRL: acia_last_read = ctrl; return ctrl; case ACIA_CMD: acia_last_read = cmd; return cmd; } /* should never happen */ return 0; }
BYTE myacia_peek(WORD a) { switch(a & 3) { case ACIA_DR: return rxdata; case ACIA_SR: { BYTE c = status | (irq ? 0x80 : 0) | 0x40; return c; } case ACIA_CTRL: return ctrl; case ACIA_CMD: return cmd; } return 0; }
static void int_acia(CLOCK offset, void *data) { //int rxirq;
#ifdef DEBUG log_message(acia_log, "int_acia(offset=%ld) myclk=%d", offset, myclk); #endif
if ((cmd &0x01) && (fd >= 0)) {
if (!(status & 0x10)) {
#ifdef DEBUG log_message(acia_log, "int_acia_write `%c' - %02x", txdata, txdata); #endif rs232drv_putc(fd,txdata); status |= 0x10; }
// and the receive buffer isn't already full if (!(status & 0x08)) {
// and receiver enabled and and RTS is low if (cmd & 0x0c) {
// and we got a byte if (rs232drv_getc(fd, &rxdata)) {
#ifdef DEBUG log_message(acia_log, "int_acia_read `%c' - %02x", rxdata, rxdata); #endif // set status that we got a byte status |= 0x08;
// if interrupts are on if (!(cmd & 0x02)) { // generate interrupt acia_set_int(acia_irq, acia_int_num, acia_irq); irq = 1; } } } } } acia_alarm_clk = myclk + acia_ticks; alarm_set(acia_alarm, acia_alarm_clk); alarm_active = 1; }
#undef DEBUG
|
|
|
Post by Golan Klinger on Mar 7, 2006 11:24:32 GMT -5
There is just one file to change in the source: aciacore.c I need to post it somewhere for download. Perhaps I will put a zip of it on my bbs. I'll keep everyone informed. I can put a compiled WinVice x64 executable up somewhere too if anyone wants it. Don't forget that if you offer a precompiled executable with changes to the source then you need to include the source in the archive along with notices stating what you changed so as to be in compliance with the GNU General Public License. You can get the specifics here: www.viceteam.org/plain/COPYING. You know, if you add functionality to VICE you should contact the authors and see if they are interested in integrating
|
|
|
Post by plbyrd on Mar 11, 2006 9:52:09 GMT -5
Please provide an AMD64 binary, or detailed instructions on how to compile an AMD64 binary from Visual Studio 2005.
|
|
|
Post by atolle on Mar 11, 2006 18:39:36 GMT -5
I've only ever got it to compile with Visual Studio 6. I tried using VS.net 2005 and it would crap out. The current v1.19 release of VICE (for which I made the mod) includes instructions on compiling with Visual Studio. You can download the source at www.viceteam.orgTo use the above mod, just locate the existing aciacore.c and replace it with the one I included above. I'm asking Jim Brain if he is interesting in implementing RFCs 2217 and 856 in tcpser java. At the same time, I am going to try to add support for it to the WinVICE. I say WinVICE because the RS232 support in VICE is all architecture-dependent. I wouldn't know how to alter the RS232 code for Linux machines.
|
|
path0s
Junior Member
Posts: 52
|
Post by path0s on Mar 17, 2006 5:02:17 GMT -5
You should submit this to the Vice team as well. I believe they like to have the patches sent to them in diff format, but I'm pretty sure that if you sent them the new file they'd figure it out.
While we're rejoycing over this feat, I dont suppose there'd be any chance whatsoever of you looking into normal userport rs232? I've got a client for a pretty amazing bbs soft that doesn't work in winvice. There's another post about it on this forum. It works fine on a real 64, and uses the transactor rs232 routines.
Yell at me if you're interested and I can get you a copy of the term and the source for the rs232..
And thanks for the work on the acia stuff! -P
|
|