Project-28 - A somewhat Minimal 6502 system

Topics related to the SBC- series of printed circuit boards, designed by Daryl Rictor and popular with many 6502.org visitors.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Project-28 - A somewhat Minimal 6502 system

Post by drogon »

gfoot wrote:
Maybe you could use "IO" instead of "PIN" to save the characters back! But I would have thought getting rid of the direction command would save a fair few bytes. And for syntax it is a departure from normal BASIC, I think, but you're already doing that for $A, ?A, !A (like BBC BASIC did) so it feels kind of natural to me.
I could be argued that the syntax is very correct - for a tiny basic from c1975 ... Also, I've a funny feeling Atom Basic was derived from the same sources, but I may be wrong...

But yes, I will save a few bytes from removing the DR command, however it does share 90% of the code with the pin read/write code to work out the bit pattern for the port mask and the 'base' address to use for the via access - setting a pin is the same code as setting the data direction register, just a different offset...

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
J64C
Posts: 239
Joined: 11 Jul 2021

Re: Project-28 - A somewhat Minimal 6502 system

Post by J64C »

drogon wrote:
Although this isn't quite true. There is actually 8KB of RAM but only 4KB is accessible. (And remember it's a 6507, so only 8K worth of address lines)

To swap RAM banks I'd need an extra output bit, somewhere. To further compound the issue, the hardware IO region is inside the RAM region and not taken from somewhere else (like the ROM area). This was a bit of a design optimisation rather than for any sort of higher speed access to the IO
Have a CPLD monitor a particular address maybe and use that as the banks switch? Could have 256 banks of RAM that way if you really wanted to couldn’t you? Can’t say I’ve thought about this in depth, so there will no doubt be many caveats and additional hardware, making a minimal system less minimal, I guess.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Project-28 - A somewhat Minimal 6502 system

Post by drogon »

J64C wrote:
drogon wrote:
Although this isn't quite true. There is actually 8KB of RAM but only 4KB is accessible. (And remember it's a 6507, so only 8K worth of address lines)

To swap RAM banks I'd need an extra output bit, somewhere. To further compound the issue, the hardware IO region is inside the RAM region and not taken from somewhere else (like the ROM area). This was a bit of a design optimisation rather than for any sort of higher speed access to the IO
Have a CPLD monitor a particular address maybe and use that as the banks switch? Could have 256 banks of RAM that way if you really wanted to couldn’t you? Can’t say I’ve thought about this in depth, so there will no doubt be many caveats and additional hardware, making a minimal system less minimal, I guess.
I think you've hit the nail there. CPLD starts to get into minimal++ territory - I already have a GAL which is doing the function of 2 (possibly 3) conventional TTL ICs to help with address decoding, handling the 8-bit latch and serial IO bits. Not to mention a little more software complexity.

However I've given it all a good thunk - plan A right now is to keep the current hardware - it's on an 90x100mm board, has a 4-bit LED output and a 1-bit button input. Take a 4K bank of the EEPROM out for a separate machine code monitor, keeping it running via serial for now - maybe an optional keypad and display through the VIA later.
project28-2.jpg
Note that the RAM chip is physically under the EEPROM chip to save board space. I got that idea from the VCF 6502 badge project.

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Project-28 - A somewhat Minimal 6502 system

Post by drogon »

So continung with the plan... I think I might have been thinking elsewhere when @gfoot said something about the peek,poke (indirection) operators. So there already is that form of syntax in there, so:

?addr = value

is the same as poke (addr, value) in other Basics. ? is poke byte, there is also ! to poke a (16-bit) word.

Similarly, reading, or peek is:

variable = ?addr

(and the same for word using !)

In computing terms, this isn't new - it was introduced in 1966 in BCPL and Acorn adopted it as their forms of peek and poke in Atom and BBC Basics.

TinyBasic takes it a little further using the $ operator for strings.

So extending the GPIO pins to use the PIN keyword is (should be) natural in this way of things. My head was probably stuck in the old "wiring" functions. Auto directioning the pins adds a few µS to execution but in reality no-one will never notice.

Now, there is an on-board button, currently read by just using variable = BTN so that fits well - there is no 'writing' the button. What about the on-board LEDs? There are 4. Currently: LED = value and it can be read with variable = LED but how about LED 0 = value or variable = LED 0 ?

I'll give it some thought.

Finally... for this little part of the process, should I keep with the literal PIN or use a symbol? PIN 4 = 1 or (e.g.) |4 = 1 Maybe that makes it a little too arcane or even shades of esoteric. (And I'm running out of spare symbols...)

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Project-28 - A somewhat Minimal 6502 system

Post by drogon »

On booting to a machine code monitor or Basic ...

There is an on-board button, so let's use it.

The system will start in Bank 0 which is the machine code monitor and support. That will start, initialise the system, copy code into RAM as required then read the button and if it's pushed then it will carry on in the monitor. If it's not pushed then it will switch to bank 1 and boot Basic. (Or maybe vice versa during my testing)

If you get to Basic and want the monitor then you can issue a CALL to some fixed/known address (might as well use $200, so CALL &200) and it will transfer to the monitor. Or just push the reset button and the 2nd button at the same time. It's very good at keeping your program in-tact, so go back to Basic and type old and it's back again.

I think that's relatively sane...

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Project-28 - A somewhat Minimal 6502 system

Post by BigEd »

Maybe use @ for PIN? Unless you've already used it of course.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Project-28 - A somewhat Minimal 6502 system

Post by drogon »

BigEd wrote:
Maybe use @ for PIN? Unless you've already used it of course.
Good idea, however it's a variable - one of the @...Z variables, however while acting as a general purpose variable, it also doubles up as the field width for printing numbers and defaults to 4 at program RUN...

Code: Select all

>PRINT 123                                                                                                                                                           
  123                                                                                                                                                                
>PRINT @                                                                                                                                                             
    4                                                                                                                                                                
>@=7                                                                                                                                                                 
>PRINT 123                                                                                                                                                           
     123
>@=0                                                                                                                                                                 
>PRINT 123                                                                                                                                                           
123
I think I'm ok with PIN for now. Seems to be working just fine and with the added bonus, as predicted by gfoot, I have bytes to spare! 15 to be precise...

Code: Select all

   10 REM Larson Scanner - All 18 output pins on the Project-28 VIA
   20 LED = 0
   30 PR "Press the button to start... "; : DO : UNTIL BTN
   40 PR "Running."
   50 DO
  100 REM Outwards
  110   FOR P = -3 TO 19
  120     H = P+2 : T = P-1
  140     GOSUB 800
  160   NEXT P
  200 REM Inwards
  210   FOR P = 19 TO -3 STEP -1
  220     H = P-2 : T = P+1
  240     GOSUB 800
  260   NEXT P
  300 REM Bump the on-board LED
  310   LED = LED + 1
  399 UNTIL BTN
  400 END
  800 REM Light the Head
  810 IF (H >= 0) AND (H < 18) PIN H = 1
  820 REM Extinguish the tail
  830 IF (T >= 0) AND (T < 18) PIN T = 0
  899 RETURN
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Project-28 - A somewhat Minimal 6502 system

Post by barnacle »

I like PIN myself. It's explicit.
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Project-28 - A somewhat Minimal 6502 system

Post by BigEd »

Umm, how did the spare bytes come about? It sounded like it would still be very tight.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Project-28 - A somewhat Minimal 6502 system

Post by drogon »

BigEd wrote:
Umm, how did the spare bytes come about? It sounded like it would still be very tight.
By removing the code to handle the "PM" or pin mode command - that's the IL code and the actual handling code.

The pin read/write code did gain a few bytes with the addition of the pin direction settings, but that was more than offset by removing the PM code. The set direction code was a bit bigger than it could have been, as I check for pins 16 and 17 so I can ignore them as they're output only. (CA2 and CB2 on the VIA)

Setting the direction bits was relatively easy as I had some common code to work out the right register (port A or B) and the bit to set or clear - and that's the same for the DDR as well as the port data register.

And now with those extra bytes, I can add back the DPOP (Do loop POP) code...

Cheers,

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Project-28 - A somewhat Minimal 6502 system

Post by BigEd »

Splendid!
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Project-28 - A somewhat Minimal 6502 system

Post by drogon »

barnacle wrote:
I like PIN myself. It's explicit.
It is, but after over 15 years of "wiring" (PIC/AVR/Pi) where the pin functions are digitalRead() and digitalWrite() it felt easier to me to use DR and DW. But now I'm using it, it does feel better and more in the style of the indirection (peek/poke) operators.

https://en.wikipedia.org/wiki/Wiring_(software)

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
J64C
Posts: 239
Joined: 11 Jul 2021

Re: Project-28 - A somewhat Minimal 6502 system

Post by J64C »

drogon wrote:
I think you've hit the nail there. CPLD starts to get into minimal++ territory
Ha! That's the thing isn't it, with these projects. "I could just add one of these. Oh, but then I'll need to add one of these because of that.". Then suddenly we have designed a CRAY T90. :lol:

The real artform and challenge is keeping it absolutely minimal (in which you are succeeding extremely well with).
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Project-28 - A somewhat Minimal 6502 system

Post by drogon »

The story so-far ...

I have written a simple machine code monitor based on my previous efforts - it's a bit "woz mon II" like because - well - that's what I first started with. I put some vectors into RAM so that other ROMs (ie. my TinyBasic) can use the monitor ROM serial code and save some space - this has freed up some 250 bytes in the TinyBasic ROM (hurrah!)

And I've managed to do this without compromising the space left over for the TinyBasic too - so it still has from $0300 through $0FFF for program (and 'dynamic') storage. (Variables @-Z are all in zero page)

At power-on time, the monitor looks for the on-board button being pressed and if it's not pressed then it boots directly into Basic. This takes a millisecond or so with most of the time spent printing out the welcome banner at 34800 bauds.

Basic, when starting, looks at the first save slot in the EEPROM and if the first line has REM! at the very start of the line then it loads that program and runs it.

So this gives the system a way to power-up and auto-start a basic program.

But if you push the button at power-on, or reset time then the monitor is started and the jump to Basic is skipped, then if you subsequently push the button and start Basic (with the @ command) then the auto-run feature is skipped. This would let you start the system into Basic without the auto-run - e.g. in some sort of embedded situation when you wanted to change the program.

(And yes, I think this is unlikely, but I'm retro-thinking here)

I think this gives you the best of both worlds.

Incidentally, the auto-start feature is borrowed from NIBL (National Industrial Basic Language) which is a TinyBasic that runs on the INS8060 CPUs (SC/MP). I understand that many of these systems were used in "industrial" scenarios during their lifetime - e.g. early computerised lift (elevator) controllers...

So power on into Basic:

Code: Select all

Ruby 6507 Computer 4K

GIBL v6

>DIR
 0:
 1: Bagels
 2:
 3:
 4: Nightmare #6
 5: Larson 4

>
Power on with the button pushed:

Code: Select all

Ruby 6507 Computer 4K

GMon v2

0000: 
and that's the monitor.

Monitor commands are like woz-mon: {address} .address action It supports memory dumping, disassembly, entering new data, going to Basic, setting he on-board LEDs and reading the button. Also moving memory and bulk zeroing or setting memory to a value.

Code: Select all

; Commands:
;       Hex                     Enter number into current address (CA), carry on...
;       #                       Comment
;       @                       Go to Basic
;       ?                       Read button
;       [ssss] !                Set LEDs to low nibble of ssss
;       [ssss] G                Run machine code from CA or ssss
;       [ssss] P                Prints (Dump) 16 bytes from CA or ssss
;       [ssss] .eeee [P]        Print (Dump) from start to end. (P optional)
;       [ssss] L                List (Disassemble) from CA or ssss
;       [ssss] : vv [vv ...]    Store into memory from CA or ssss
;       [ssss] .eeee Z          Zero memory from CA or ssss through eeee
;       [ssss] .eeee > tttt     Move memory from CA or ssss through eeee to tttt
;       [ssss] .eeee / vv       Fill memory from CA or ssss through eeee with value
;       [ssss] +vvvv            Add CA or ssss to vvvv, display result.
;       [ssss] -vvvv            Sub vvvv from CA or ssss, display result.

there is still 1¼ Kbytes free - could be more as I've not really tried to golf the code size down for now. I may add in a breakpoint handler and maybe mini-assembler but I feel thee may be little need for it all.

There is now a set of vectors and a small amount of code in RAM starting at $0180 - middle of the 6502 stack. There is exactly 32 bytes of stack free for programs to use. Possibly sub-optimal, but the Monitor uses little and Basic just as little. (Basic resets the stack pointer to $EF at startup and uses 17 bytes at most)

Code: Select all

0000: 100.1ff
0100: 31 30 30 2E 31 46 46 0D AA AA AA AA AA AA AA AA  | 100.1FF          |
0110: AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA  |                  |
0120: AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA  |                  |
0130: AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA  |                  |
0140: AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA  |                  |
0150: AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA  |                  |
0160: AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA  |                  |
0170: AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA  |                  |
0180: 4C CA 01 4C BD 01 4C 9C 01 4C AB 01 4C B4 01 48  | L  L  L  L  L  H |
0190: A5 E5 85 20 29 8F 85 E5 85 F8 68 60 20 8F 01 20  |     )     h`     |
01A0: BA 10 48 A5 20 85 E5 85 F8 68 60 20 8F 01 20 F9  |   H      h`      |
01B0: 10 4C A2 01 20 8F 01 20 6C 11 4C A2 01 A5 E5 29  |  L      l L    ) |
01C0: 8F 09 90 85 E5 85 F8 6C FC FF 20 8F 01 4C DE 11  |        l     L   |
01D0: AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA  |                  |
01E0: AA AA AA AA AA 10 00 06 09 D0 09 06 6B 15 7B 13  |               {  |
01F0: 00 00 00 00 0B 52 BA FB DE B0 FF 00 00 00 80 00  |          b       |
I initialise page 1 to AA so I can keep an eye on it. Note $1Fx is the VIA, so usable stack is from $1EF down through $1D0. $100 through $17F is the keyboard input buffer. There is some wiggle room here - even by reducing the size of the input buffer down to (say) 96 bytes (just to make it an easy number for the start of the vectors, so $160 rather than $180) would be more than acceptable.

For the curious the code there is: (Using the disassembler)

Code: Select all

0200: 180L
0180: 4C CA 01  <L..L..> JMP   $01CA
0183: 4C BD 01  <L..L..> JMP   $01BD
0186: 4C 9C 01  <L..L..> JMP   $019C
0189: 4C AB 01  <L..L..> JMP   $01AB
018C: 4C B4 01  <L..H..> JMP   $01B4
018F: 48        <H... )> PHA
0190: A5 E5     <... ).> LDA   $E5
0192: 85 20     <. )...> STA   $20
0194: 29 8F     <).....> AND   #$8F
0196: 85 E5     <....h`> STA   $E5
0198: 85 F8     <..h` .> STA   $F8
019A: 68        <h` .. > PLA
019B: 60        <` .. .> RTS
019C: 20 8F 01  < .. ..> JSR   $018F
019F: 20 BA 10  < ..H. > JSR   $10BA
01A2: 48        <H. ...> PHA
01A3: A5 20     <. ....> LDA   $20
01A5: 85 E5     <....h`> STA   $E5
01A7: 85 F8     <..h` .> STA   $F8
01A9: 68        <h` .. > PLA
01AA: l
01AA: 60        <` .. .> RTS
01AB: 20 8F 01  < .. ..> JSR   $018F
01AE: 20 F9 10  < ..L..> JSR   $10F9
01B1: 4C A2 01  <L.. ..> JMP   $01A2
01B4: 20 8F 01  < .. l.> JSR   $018F
01B7: 20 6C 11  < l.L..> JSR   $116C
01BA: 4C A2 01  <L....)> JMP   $01A2
01BD: A5 E5     <..)...> LDA   $E5
01BF: 29 8F     <).....> AND   #$8F
01C1: 09 90     <......> ORA   #$90
01C3: 85 E5     <....l.> STA   $E5
01C5: 85 F8     <..l.. > STA   $F8
01C7: 6C FC FF  <l.. ..> JMP   ($FFFC)
01CA: 20 8F 01  < ..L..> JSR   $018F
01CD: 4C DE 11  <L.....> JMP   $11DE
01D0: AA        <......> TAX
But really the only thing of interest is the first few JMP instructions which programs can use to call/goto various things. Also, the reason there appears to be so-much code there is the need to fiddle with the EEPROM bank-select register, keep a soft-copy (or 2) so we can correctly return to the ROM that called the routine. This code needs to be outside the ROM area...

Code: Select all

; Vectored routines:

goMonV:         jmp     goMon2          ; $0180
goBasicV:       jmp     goBasic2        ; $0183
putCharV:       jmp     putChar2        ; $0186
getCharV:       jmp     getChar2        ; $0189
getLineV:       jmp     getLine2        ; $018C
You could drop into the monitor, do "stuff" and come back again:

Code: Select all

>NEW

>10PRINT "Hello, world!"
>20END
>RUN
Hello, world!

>CALL &180
GMon v2

0000: 300.3ff
0300: 00 0A 19 50 52 49 4E 54 20 22 48 65 6C 6C 6F 2C  |    PRINT "Hello, |
0310: 20 77 6F 72 6C 64 21 22 0D 00 14 07 45 4E 44 0D  |  world!"    END  |
0320: FF FF 00 40 80 08 FF FF FF FF 00 08 00 00 00 00  |    @             |
0330: 00 E0 FF FF FF FF 34 C8 00 B1 FF FF 6B C9 48 F6  |       4     k H  |
0340: FF FF A4 10 00 C0 FF FF FF FF 08 15 01 B4 FF FF  |                  |
0350: 00 20 FF FF FF FF 00 08 80 02 FF FF FF FF 00 84  |                  |
0360: FF FF 00 08 00 00 FF FF FF FF 00 00 00 00 FF FF  |                  |
0370: 00 02 FF FF FF FF 00 24 00 70 FF FF FF FF 10 00  |        $ p       |
0380: FF FF 48 45 40 80 FF FF FF FF 20 0E 02 88 FF FF  |   HE@            |
0390: 00 10 FF FF FF FF 00 00 00 00 FF FF FF FF 00 00  |                  |
03A0: FF FF 00 40 14 00 FF FF FF FF 00 00 00 08 FF FF  |    @             |
03B0: 00 04 FF FF FF FF 00 19 60 65 FF FF 37 6C EB B5  |         `e  7l   |
03C0: FF FF 00 00 05 A0 FF FF FF FF 48 88 02 88 FF FF  |           H      |
03D0: 80 00 FF FF FF FF 00 00 00 40 FF FF FF FF 10 10  |          @       |
03E0: FF FF 00 21 40 88 FF FF FF FF 02 00 00 00 FF FF  |    !@            |
03F0: 00 25 FF FF 4E 1B A7 B3 00 91 FF FF 26 FE B1 95  |  %  N       &    |
0400: 183G
GIBL v6

>OLD

>LIST
   10 PRINT "Hello, world!"
   20 END

>
So that's about that for now. Comments/Suggestions welcome and I'll make a little video of it soon...

Cheers,

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
gfoot
Posts: 871
Joined: 09 Jul 2021

Re: Project-28 - A somewhat Minimal 6502 system

Post by gfoot »

Very nice. I like the attention to detail regarding the startup options, bypassing auto-run, etc. I think if a program did need more stack space then it could either not use the OS vectors, or copy them somewhere else on startup, so it feels quite nice all round I think.
Post Reply