A Minimal Interactive Environment

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Post Reply
enso1
Posts: 197
Joined: 30 Jul 2024

A Minimal Interactive Environment

Post by enso1 »

Once you can communicate with your '02 system via a serial port and are running a monitor (or a Forth or BASIC) via a serial port terminal on a PC, things get awkward.

I am always envious of a Lisp-like environment -- a full-screen editor capable of sending text to the target when desired. This allows for easy code development (editing files) and selectively sending things like Forth definitions or data into the monitor. Luckily, this can be accomplished without an IDE, with GNU screen and a single line of vimscript.

Since I always forget how to do this, I will immortalize the recipe here. Enjoy.

Required:
* GNU screen utility Used as a serial port terminal, but can do so much more...
* vim, my editor of choice, but Emacs or any programmable editor is capable of this...

Strategy:
* Start a named screen session to the target and as a general-purpose terminal.
* Configure vim to send a line of text and scroll down one line, bound to Ctrl-l.

Recipe:
Alter to fit your circumstances. I use 'potato' as the session name, and connect on port /dev/ttyUSB1 at 115200 baud.

Add (as one line) to .vimrc:

Code: Select all

nnoremap <C-l> :let @a = getline('.')<CR>:call system('screen -x potato -X stuff "' . escape(@a, '\') . '\r"')<CR>:normal! j<CR>
Start a screen session:

Code: Select all

screen -S potato /dev/ttyUSB0 115200 
Make sure you can communicate to your device.

Start vim and enter a few lines of code or whatever you may normally send to your target, put the cursor on the first line, and press Ctrl-l for every line you want sent.

That's all there is to it.
---------------------------------------------
Improve as you need to -- sending entire Forth definitions, or the complete contents of a file is pretty easy. And anything capable of executing a command line can send to your target using the following template:

Code: Select all

screen -x potato -X stuff "Hello there\r\n"
If you need direct access to the serial port -- maybe to send a binary -- you can detach the screen session with <Ctrl-A><D>, do your business, and reattach with 'screen -r potato'.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: A Minimal Interactive Environment

Post by GARTHWILSON »

The way I linked to earlier (http://wilsonminesco.com/BenchCPU/#ctrl) is simpler.  Use any text editor that can mark a block and "print" it to RS-232.  In my MultiEdit editor, I mark the block with the mouse, as little as 1 character or as much as many pages, press <Alt>F (for "file operation"), P (for "print"), and if you already have the output device set to the right port, just press <Alt>B (for "block").  The Forth takes in that text and interprets, compiles, or assembles, on the fly, as appropriate.  Forth allows writing a new code fragment and trying it instantly, with no need to recompile your whole application to integrate it.  It becomes part of the language, even though it goes into RAM, not ROM.  I don't suspend or background the editor, nor do I use any scripts, nor is a multitasking system needed, nor any TSRs.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
enso1
Posts: 197
Joined: 30 Jul 2024

Re: A Minimal Interactive Environment

Post by enso1 »

For those lucky enough to use DOS, true enough!

Linux makes it really hard to use a simple printer. I have an Oki Microline, and about a decade ago I managed to get it working over a USB-parallel cable (no more parallel ports...) -- it took me about a day of headbanging and searching the web for hints on how to do that using some old driver. And then I updated linux and it stopped working. [To be fair, I was trying to install it as a generic printer -- sending data to the port works but I'd need to deal with each program individually, or use cp and replace <CR>s with <LF><CR> with sed or something...]

As a born-again Vim user, I would hate to pick up the mouse to select text! I didn't bother mentioning it as every Vim user knows these tricks but you can always send, say 6 lines, by doing '6<C-l>', or if the last thing you did was send a line, just press the '.' key or '6.'

I kind of like sending a line at a time when I am debugging -- I have a bunch of interesting lines that I switch between, and since I have no handshake, sending a line at a time avoids all kinds of problems...

But if you want to send selected text, for instance, you can make a (visual mode) binding like

Code: Select all

vnoremap <C-l> :<C-u>let @a = join(map(getline("'<", "'>"), 'v:val . "\r\n"'), "")<CR>:call system('screen -S potato -X stuff "' . escape(@a, '\') . '"')<CR>
Now <C-l> will send a line at a time in normal mode, and selected text in visual mode.

P.S. normally you don't need to disconnect the screen session, that is only in case you need access to the port, because screen locks the port for itself...

P.P.S. I don't write the vimscript gobbledygook myself, I just ask ChatGPT! It's actaully a pretty good assistant, as long as you know what you are doing in the first place and can check its work. It's kind of like hiring a gen-z person, except ChatGPT knows what it's doing most of the time, and you don't have to pay it, or walk on eggshells about offending it by asking it to do its job right or forgetting its pronoun.
Last edited by enso1 on Mon Mar 24, 2025 3:10 pm, edited 1 time in total.
enso1
Posts: 197
Joined: 30 Jul 2024

Re: A Minimal Interactive Environment

Post by enso1 »

Actually, I just noticed that GTKTerm does not acquire a lock on the serial port! It is a pretty good serial terminal, and makes it really easy to send binaries to the target. And since the port is available for other programs, the following vim binding just sends data directly to the port (/dev/ttyUSB1 in my case):

Code: Select all

nnoremap <C-l> :let @a = getline('.')<CR>:call system('echo -ne "' . escape(@a, '\') . '\r"> /dev/ttyUSB1')<CR>:normal! j<CR>
That is almost as straightforward as in DOS.
enso1
Posts: 197
Joined: 30 Jul 2024

Re: A Minimal Interactive Environment

Post by enso1 »

Here is a better vim binding (the last one works, but you cannot repeat it with a . or prefix with a number of times to do it -- Vim has some stupid limitation about system calls)

Code: Select all

function! SendLineToPort()
  let @a = getline('.') 
  let escaped_line = escape(@a, '\\$')
  let escaped_line = substitute(escaped_line, '"', '\\"', 'g')
  call system('echo -ne "' . escaped_line . '\r" > /dev/ttyUSB1')
  normal! j
endfunction

nnoremap <C-l> :call SendLineToPort()<CR>
For some reason when the system call is wrapped in a function, Vim allows repeats.

Edited to escape $ mangled by vim
Last edited by enso1 on Tue Mar 25, 2025 2:30 pm, edited 1 time in total.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: A Minimal Interactive Environment

Post by drogon »

enso1 wrote:
Once you can communicate with your '02 system via a serial port and are running a monitor (or a Forth or BASIC) via a serial port terminal on a PC, things get awkward.
Do they?

So what I did was to throw away the monitor and adopt what I had on a 6502 system in 1981 (BBC Micro) and extend that to give me nice command-line editing and history recall, along with the ability to run code directly from local storage. Everything then runs under this operating system and reaps the benefits of that command line interface. The OS provides for file transfer over the serial line in a transparent way to the "smart" terminal program running on my Linux host which handles graphics as well as text. (Although the local filing system on SD card is FAT so that's also easy to exchange data with a modern PC).

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Post Reply