EhBASIC input on 6502 emulator - c

I have been working on this 6502 emulator for a while, and I'm tying to get a simple Enhanced BASIC ROM to work. Although it lacks precise clock timing, the emulator did pass AllSuiteA.asm.
With EhBASIC, I've managed to get some output by printing the value of $F001 when a read is done to that address.
if(lastwrite == 0xF001)
{
printf("%c",CPUMEM[0xF001]);
}
However, I have no idea how to emulate the input process. This post states that whenever EhBASIC wants input, It will poll $F004. But my current code seems to have two problems:
while(1)
{
decodeandexecute();
if(lastread == 0xF004)
{
inputchar = getchar();
CPUMEM[0xF004] = inputchar;
}
if(lastwrite == 0xF001)
{
printf("%c",CPUMEM[0xF001]);
}
}
Input is only possible through individual letters (Expected)
After the program asks for memory size, giving any input will just cause a loop of reading from $F004 (LDA $F004) - i.e. I can't let EhBASIC know when to stop receiving inputs
I want to know an effective method of entering a string of characters, and getting passed "memory size?".
Additionally, if I want to let EhBASIC calculate the memory size automatically, what should I input to $F004?
I'm pretty much a newbie in this area....

I see you use getchar in the code and if I remember correctly that is a blocking call (it will wait until someone presses some key).
In the manual of ehbasic it says:
How to.
The interpreter calls the system routines via RAM based vectors and,
as long as the requirements for each routine are met, these can be changed
on the fly if needs be.
All the routines exit via an RTS.
The routines are ...
Input
This is a non halting scan of the input device. If a character is ready it
should be placed in A and the carry flag set, if there is no character then A,
and the carry flag, should be cleared.
One way to deal with this is to use two threads. One thread that runs the emulation of the 6502 running ehbasic and another thread that polls the keyboard.
Then let the polling thread push any input key strokes into a small buffer from which the ehbasic input routine can use.
Manual: http://www.sunrise-ev.com/photos/6502/EhBASIC-manual.pdf
UPDATE
Reading the question/answer you linked to, I see it is a modified ehbasic.
Your keyboard polling thread should place the keystrokes read in $F004 (and after a while clear F004 again - if I understand the instructions).
UPDATE 2
As a debugging tip: In you first version simply have a string with a fixed input such as 10 print "hello" 20 goto 10 and feed $f004 from there. That way you don't have to worry about any problems with using an actual keyboard.

Related

C: Is there a way to lower the speed of printf-outputs

as said in the heading, is there a way to lower the speed of printf-outputs in C? Just like watching every character getting printed in particular (it does not have to be so slow, just so you understand what i mean).
The reason why i ask is:
I need to program a small microcontroller. But every 'printf' executed on it should be send back to the com1 port of the host. Everything works fine, I already buffered my printf so everything will be stored in a char-array with a finit size and this array will be sent back to com1 char by char. But because i don't know how many printfs there will be, and because of the limited memory of the μC, a size-limited array isn't the best solution. So my new attempt is to write directly to the send-register of the μC, which can only contain one char at a time until its sent. I do this via
setvbuf(stdout, LINFLEX_0.BDRL.B.DATA0, _IOFBF, 1);
where LINFLEX_0.BDRL.B.DATA0 represents the transmit-register. What I think what my problem is now: the printfs just overwrite the register to fast, so it has no time to send any char stored in it before it gets changed again. When sending char by char from the array, i wait until a data-transmission-flag is set:
//write character to transmit buffer
LINFLEX_0.BDRL.B.DATA0 = buffer[j];
// Wait for data transmission completed flag
while (1 != LINFLEX_0.UARTSR.B.DTF) {}
// Clear DTF Flag
LINFLEX_0.UARTSR.R = 0x0002;
So the idea is to slower the speed the printfs processes every character, but feel free to comment if anyone has another idea.
The problem isn't with printf as such but with the underlying UART driver. That's what you'd have to tweak. If you are using Codewarrior for MPC56 you can actually view the source code for all of it: quite horrible code. Messing with it will only go bad - and apparently it doesn't seem to work well in the first place.
Using printf in these kind of embedded applications is overall a very bad idea, since the function is unsuitable for pretty much any purpose, UART communication in particular. The presence of printf is actually an indicator that a project has gone terribly wrong, quite possibly it has been hijacked by PC programmers. That's not really a programming problem, but a manager one.
Technically, the only sane thing to do here is to toss out all the crap from your project. That means everything remotely resembling stdio.h. Instead, write your own UART driver, based on the available Freescale examples. Make it work on bytes. This also enables you to add custom features such as "echo", where the MCU has to wait for a reply from the receiver. Or you could implement it with DMA if you just want to write data to a buffer and then forget all about it.

Parsing AT commands & responses in a circular buffer

I have a PIC32MM connected via UART with BT module RN4020 and currently struggling with it's configuration. It uses AT-command format COMMAND+CR+LF (or corresponsive ANSWER+CR+LF).
First, the module is set via special signal line into Command Mode, which after boot-up gives "CMD\r\n" on MCU's RX line. I am using default nifty functions provided by MPLAB IDE, which are based on circular buffers filled byte by byte during RX interrupt routine and I think I've already grasped the simple principle of how they work.
There even is a neat function ReadBuffer(target string, num of bytes to read) provided, which reads given amount of bytes from the rx circ buff into a given char array (buffer, string) to work with then.
My question is - what might be the best way to wait for and recognize a correct answer and then after it came and is checked, which means the module is ready for a command to be send via TX line, send a command. I need to signalize the moment when the answer from the module is fully read in MCU - in other words, when to call the ReadBuffer function so it gives me correct string back and I can be sure that I call ReadBuffer(my_target_string, 5) and my_target_string contains "CMD\r\n". I don't want to move the Head&Tail pointers unnecessarily wrongly, and mess up the structure. Is some kind of timeout a good way to proceed or is it even better to create some indicator flag and (un)set it when CR and LF come?
Thanks for any ideas or hints in advance.
After finding out, that the answer's home, some sort of string compare might be enough to check if it is what is expected I think. (Tricky might be '\0' character, but I'll try to keep that one in mind.)

Waiting maximum of X time for input, then proceeding with the program?

Hello I'm creating a game in C.
I want there to be a frame printed every 0.1 seconds. During that time, the user may or may not input using getch().
How do I write such a program? Heres what I can offer you guys to work with.
do{
usleep(100000); // simple 100 mili second delay
if (getch()==32) (ASCII for a space) // may or may not be inputed in 0.1 second timeframe.
playerJumps;
// even if user inputs early, I still want game printed exactly every 0.1 sec not sooner/later.
printGame;
}while(notDead);
I really hope I kept code nice and clear
I've done this before, you are going to have to talk about what platform you are on. All of the C library input functions block to wait for input. One way to do it is with threads -- you have one thread block on the user input, and the other does the game, and it gets notified by the input thread when there is input. The other way is to use a function like poll() on linux, which I believe is what I used, they basically allow you to specify a wait period, or to just try to see if there is input and return immediately if there isn't. Though I think select() should also work, and I think that should be relatively cross platform.

How to wait for a response, while running an asyncronous serial communication?

I am a bit unsure about this question, but I constantly running into troubles with my current design, and would be really greatful, if someone could show be a different approach to this.
My program writes async commands to a device via rs232, while constantly reading and reacting to received data.
This works all nice and neat, but during my init-phase, I have to send a bunch of commands, which would have to wait for a response, before letting the program countinue.
Now, this part I have to do in plain C, and all I could come up with was to use global vars and while loops. But I find this really not pretty.
Take this as an pseudo-code example:
OnReceive(data){
switch determineCommand(data)
case CMD1:
config.value1 = data.value1
case CMD2:
config.value2 = data.value2
default:
print data
}
DoCommandChain(){
Send(CMD1)
If("Send(CMD1)" got its response){
Send(CMD2)
}
}
Now, the problem is "If XY got its response" - because I don't want to use some vars to detect this and I can't rely on a return value for Send(CMD1), because this is just an indicator, that CMD1 was send - not there was something corresponding received.
I am asking here, because I would like to know what I could search for / read about, to solve this mess in a nice way.
Right now, my best idea for this would be to somehow setup a timer-guarded-function to monitor, if a specific response is received. Then, depending on the status of this response, go to the next Send or retry the last.
Like this:
Instead of `Send(CMD1)` -> `DoUntilResponse(Send(CMD1),Timeout,NumberOfRetries)`
DoUntilResponse(function,Timeout,NumberOfRetries){
registerExpectedResponse(CMD1, gotResponse) //awaiting some response for CMD1
for(i=0 ; i!=Numberofretries; i++){
if (Send(CMD1) == successfulSend ){
while(not timeout){
if gotResponse then break;
}
if gotResponse then break;
}
}
}
Edit:
Just to clarify: I am not worried about the serial-connection, or about how to fire the OnReceive function - this is all working already. What I can't get a clear idea of, is how to solve the above pseudo-code without the use of polling and preferably in pure C.
Assuming that write and read operations are executed in different threads, use the following algorithm:
Write thread.
Register expected response.
Send packet to the device
Wait for Received event with timeout. If event is set, continue. Timeout -
report error and exit (or make additional trial).
Read thread.
For every received packet:
Add it to the input buffer.
Analyze buffer. If it contains valid response, set "Received" event,
releasing the Write thread, clear input buffer, and continue reading.
If input buffer contains unrecognized data, report error, clear buffer
and continue reading.
If input buffer contains the beginning of expected response,
continue reading.
Threading and event notification is OS-specific. If your C++ compiler doesn't support multithreading, use portable library like Boost, or use OS-specific API. Notice that Read thread implements stream parsing logic, since serial communication is stream-oriented.
Edit.
"Register expected response" means: set some program variable(s) than mean "Command of type X is sent to device". According to this variable, Read thread expects to receive the packet, which should be sent by device according to communication protocol (application-specific). Another received packet, which may be generally valid, should be treated as error, because this is not response to the command just sent to device.
Another way: Set expected response size. In this case, once Read thread received expected amount of data, it sets Received event, leaving packet recognition task to the sender.
It is operating system specific. On Linux or Unix you should consider using a multiplexing syscall like poll(2) (or perhaps select(2) which I feel is obsolete, because it limits the maximal file descriptor number, see the C10K problem).
The C standard don't know about serial ports.

serial device ignores EscapeCommFunction with C

I am migrating (finally) from MSDOS to Windows XP for controlling a meter via the serial port. My old C DOS code works fine.
I want to do as follows:
meter is continuously taking readings
every few sec, but does not send any
info until it is requested by the
computer
when computer is ready to receive
info from meter, it requests it. It does not accept info otherwise.
My problem is that the readings are just coming into the computer as they are generated by the meter.
I have set the DCB serail params as follows, intending to control communication using RTS and DTR:
dcbSerialParams.BaudRate=CBR_4800;
dcbSerialParams.ByteSize=7;
dcbSerialParams.StopBits=TWOSTOPBITS;
dcbSerialParams.Parity=EVENPARITY;
dcbSerialParams.fDtrControl=DTR_CONTROL_ENABLE;
dcbSerialParams.fRtsControl=RTS_CONTROL_ENABLE;
My old code under DOS was like this:
outportb(COM1+4,0x03); /* start Minolta reading */
for(j=0;j<=10;j++) /*each reading consists of 11 ascii characters*/
{
while(!((inportb(COM1+5)) & 1)); /*wait until char received*/
reading[j]=inportb(COM1);
}
sscanf ( &reading[4], "%f", &lum[k] );
outportb(COM1+4,0x00); /* stop Minolta reading */
It seems to me that this should work:
void serial_notready(void)
{
EscapeCommFunction(hSerial,CLRDTR);
EscapeCommFunction(hSerial,CLRRTS);
}
void serial_ready(void)
{
EscapeCommFunction(hSerial,SETDTR);
EscapeCommFunction(hSerial,SETRTS);
}
int serial_read(char reading[])
{
DWORD dwBytesRead = 0;
int nbytes=11;
ReadFile(hSerial, reading, nbytes, &dwBytesRead, NULL);
return(dwBytesRead);
}
serial_ready(void);
x = 0; while(x == 0){x=serial_read(reading);}
serial_notready(void);
HOWEVER, the Minolta does not wait to receive the RTS from the computer. It just goes ahead and sends readings as each becomes available. At the same time, the computer does not reject any unwanted reading, but accepts it.
I have been bashing my head against the wall trying to figure this out, trying all kinds of permutations to no avail. Any help greatly appreciated!
Update:
The underlying story is that I present a given luminance (brightness) on a display and then need the corresponding luminance reading. This is done for a whole set of luminances.
L ---
U ---
M ---
TIME
I present lum1, lum2, lum3, lum4,.... If the measurements are not synchronised to the display, then I may get a supposed reading3 that is actually lum2, or some sort of average because the reading crossed the border between the lum2 and lum3 displays. And, as you said, Hans,the readings will always lag behind the display luminances. Even if I were always systematically one reading behind it would be bad (my situation is worse-- it is a a random relation between the reading and the luminance).
So the behaviour of the windows serial routines is a nightmare for me. Thanks again for the help!
dcbSerialParams.fDtrControl=DTR_CONTROL_ENABLE;
dcbSerialParams.fRtsControl=RTS_CONTROL_ENABLE;
You enable the DTR and RTS signals right away. The meter will immediately start sending data when you open the port. That data gets buffered in the driver's receive buffer. You didn't have a buffer before in the DOS code. It depends how long it takes for you to call serial_notready(). You'll have a pretty full buffer if that takes a second or so. Yes, that makes it look like the meter is just sending data. And you are always reading an old sample.
Start with the DCB values set to DISABLE. Beware that the scheme is brittle, you could turn the signal off pretty reliably back in the DOS. Now you've got a driver in between. You may well end up turning RTS off too late. Which risks getting a stale reading. An alternative is to startup a thread that just reads continuously. And have your main code just use the last value that it read. The overhead is quite low, serial ports are slow.
The first thing to do would be to check the return values of the calls to EscapeCommFunction(). If the return value is zero, the call failed and you should use GetLastError() to receive more error information.
I use a free third party serial port emulator VPS. its got a interval request timer that dectate when excatly the data need to be updated/grapped. also allow me to log the bus packets into an excel file.

Resources