Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Stefan

  1. I think it's great that David so openly shared this information with the community. We could feel that there were hurdles, but it's better to have first hand information. If money is no object, I'm personally most interested in the phase 1, whether in kit form or pre-assembled. Converting assembly programs from X16 to X8 may very well prove to be a hassle. The differences, as described, seem to be quite substantial: no banked RAM, less VRAM and different access logic to VERA. It feels like X16 and X8 are no more related than cousins, like VIC20 and C64 for instance. A X16 program could be ported to X8 but would take some effort and the result would in many cases be restricted in some ways. Attracting developers and building a sufficient software library might be the most demanding aspect of successfully launching a new computer platform. Therefore you need to think carefully before dividing the developer efforts between two platforms.
  2. As I now might have the basis for a transport layer over I2C I'm thinking about a communication protocol. So far this is what I have in mind. X16 to RPi requests The first data byte sent would select a command to be executed on the RPi The rest of the data sent would be command specific A command that invokes the Linux program lp to print a file could be formatted as follows: A null terminated string containing the command line params to be given lp Then the content to be printed as a stream of characters/bytes A command that invokes curl to fetch a web resource could contain the following: A null terminated string containing the params to curl RPi to X16 responses Reading from the RPi would always return the response of the last command. The response could be formatted as follows: One byte: Response code (interpretation command specific) Three bytes: Length of response stream (three bytes addresses more than a fully expanded X16) The actual response stream Please let me know if you see problems or better ways of doing this.
  3. I've made some small progress. I have managed to setup a Raspberry Pi Zero W as I2C slave and a Ardunio Uno as I2C master: Electrical connections The Arduino is powered by USB The RPi is powered from the Arduino 5V pin to RPi pin 2 (5V) The Arduino ground is connected to RPi pin 6 (GND), ensuring a common ground I have a voltage level converter (5V/3.3V). This is driven by the 5V and 3.3 V outputs of the Arduino. Arduino pin A4 (SDA) is connected to the voltage level converter 5V side. The low voltage side is connected to RPi pin 12 (GPIO 18) Arduino pin A5 (CLC) is connected to the voltage level converter 5V side. The low voltage side is connected to RPi pin 35 (GPIO 19) The Arduino runs a program that sends the text "Hello world" once every second to I2C slave address 4 The RPi runs a loop that listens on that slave address and prints incoming text to the terminal Arduino code #include <Wire.h> void setup() { // put your setup code here, to run once: Wire.begin(); } void loop() { // put your main code here, to run repeatedly: Wire.beginTransmission(4); Wire.write("Hello world"); Wire.endTransmission(); delay(1000); } RPi code The code I used on the RPi is basically identical to the example/instruction published here: https://raspberrypi.stackexchange.com/questions/76109/raspberry-as-an-i2c-slave Attached is a short video showing this contraption running. Not Ben Eater quality, I'm afraid But hopefully you get the idea. IMG_0228.MOV
  4. Thanks @Lorin Millsap! I looked at and calculated the wait loop on lines 55-60 in the file x16-rom/kernal/drivers/x16/ps2.s (Github master branch) once more. AFAIU: The loop setup on lines 55-56 is 4 cycles. The loop counter (Y) is set to 80. Each loop (lines 57-60) takes 11 cycles. The test for a start condition happens 4 cycles into the loop. The loop will check for a start condition 79 times The last check will happen 4 + 78*11 + 4 = 866 cycles after the I2C lines were released 866 cycles @ 8 MHz processor speed is about 108 us. @ 2 MHz it's about 433 us. If the keyboard hasn't started to transfer data within that time, the PS/2 lines are made inactive again. As far as I can see, there are no other parts of the Kernal PS/2 code that has a similar timeout. If receiving a start condition, the code will wait (indefinitely) for the keyboard to finish transmission. Instead of lowering the processor speed, you could increase the value of the loop counter on line 56. If the counter is set to it's maximum value of 255, the timeout will happen after 349 us. If that's not enough, you could add one ore more NOPs to the loop for testing purposes. One NOP at the beginning of the loop would increase the wait to about 414 us if the loop counter is set to 255.
  5. I remember @Lorin Millsap said some months ago, that the current Kernal function for reading the keyboard would not be the one to be used in the final product. On Github, there is the "ps2-nmi" branch last updated at the end of April. I haven't analyzed the code, but it seems to be an interrupt based solution instead of the polling method used in the current master branch.
  6. David made an interesting update on Youtube today. Apparently there is some kind of timing issue when reading the keyboard. It works reliably only when the board is operating av 2 MHz. David said it was probably "software" related, i.e. the Kernal's PS/2 driver. AFAIA, the Kernal holds the PS/2 clock and data lines inactive most of the time. When it's ready to receive data from the keyboard, the lines are released, and (I suppose) pulled high by a pull-up on the VIA pins. The Kernal then polls the state of the PS/2 lines for about 100 us. If the keyboard has not begun sending data within that period of time, the Kernal pulls the clock and data lines to the inactive state again, and continues with other chores. The PS/2 protocol gives devices some leeway when it comes to timing. I haven't found any specification on how fast a device must start sending data after the clock and data lines are released by the host. It is only said that communication may not start before 50 us after the lines were released. It is possible to let the Kernal wait longer for the keyboard to start sending data. The drawback is, of coarse, that this holds up the whole system. The current waiting period of about 100 us is 0.6 % of the vertical blank at 60 Hz. Multiplying the waiting time by four (corresponding to the transition from 8 MHz to 2 MHz) would make it 2.4 % of the vertical blank. That is still OK. To test if this actually solves the problem, you would only need to change the value "10" on line 56 in the file x16-rom/kernal/drivers/x16/ps2.s (Github master branch). I look forward to follow the crew solving these last gremlins.
  7. I guess we all agree with @TomXP411 on how the cursor should work. Still in R39, when you hold down a key, the cursor is mostly hidden. Maybe not a big problem, but it doesn't look good. Some other things I've observed if you were to build the perfect cursor: In ISO mode there are no inverted characters. When the cursor is turned on standing over a character you cannot see what's behind it in R38/R39 when in ISO mode. Not a big problem as you can see the character during the period when the cursor is off, but still not perfect. If in 16 color text mode, you could make a cursor that swaps the background and foreground colors instead of changing the character. That looks the same as inverted characters in PETSCII mode, and it would work in both PETSCII and ISO mode. In the X16 Edit R39 version I'm using this technique, and it works very well. However, in 256 color text mode, you cannot change the background color of individual characters. The color swap method would not work The only method I can think of that would work in ISO mode + 256 color text mode is to use a sprite The sprite would be just a filled box in the foreground color of the same size as a character (the same as an inverted blank space that is) The Z-depth of the cursor sprite would be behind layer 0 and 1 but in front of the background When the cursor is turned on, the sprite is made visible at the right position and the character color is changed to the background color of the screen It should look like an inverted character, but I haven't actually tested it The drawback is that you are using one sprite To cover all modes you would need at least two alternative cursor functions One using the color swap method when in 16 color mode One using the sprite method when in 256 color mode
  8. Hi Philip, Have you thought about making your own cursor from scratch? It's not that hard to do, and you are not relying on Kernal code subject to change. /Stefan.
  9. Some thoughts on X16 <-> RPi communication As far as I can tell, the X16 Kernal is bit banging the I2C protocol. I do not know what speed we are to except. Furthermore, I assume from skimming over the X16 Kernal source code that it will only work in I2C master mode Making the RPi act as an I2C slave might not be straightforward, but there seems to be a hardware supported slave mode I found this discussion thread on using the RPi as a slave Link: https://raspberrypi.stackexchange.com/questions/76109/raspberry-as-an-i2c-slave According to this, you must use GPIO 18 and 19 in slave mode (not the same pins as in master mode) My old RPi (actually the first version ever launched) does not expose those two pins. I need to buy a newer RPi. I have ordered a RPi zero W, which I understand has both GPIO 18 and 19 linked to the header. If anyone of you have practical experience on how to set up an RPi as an I2C slave, please share. If it's possible to make this work, that opens a lot of possibilities beyond printing: You could get access to the Internet over the RPi (even over WiFi) You could use the RPi to store files (may not be very interesting, an SD card holds a lot of data) You could communicate with other USB devices than printers My plan is to build a test rig with an Arduino as I2C master and RPi Zero W as slave. The Arduino has good I2C support and is mostly using 5V levels as the X16, so I can test that the voltage level converters I have at home are good (fast) enough for this application.
  10. I continued on making a PostScript template that could be used as the basis for a printing solution. After some initial hurdles, I come to like PostScript a lot. The template is attached. Some remarks: There are some variables you may set in the header pagh = page height pagw = page width lmarg = left margin bmarg = bottom margin tmarg = top margin rmarg = right margin leading = line spacing All of those in points, 1 inch = 72 points Custom procedures defined in the header normal = select default font, in the template that's Courier 10 pt NP = Create new page NL = New line PR = Print text string (one or many lines) The template supports printing with Latin1 encoding I have written this template mostly with the needs of X16 Edit in mind. I could make X16 Edit output the PostScript header quite easily. The header could be condensed by removing comments and white space. It should then be less than 1 kB. You then need to continue to output the actual content to be printed. Enclose each line of text to be printed in parenthesis. That's the way PostScript marks strings, not using quotes as most programming languages Thereafter call PR to print and NL to insert a line break After all text has been outputted you lastly need to call the showpage function The actual printing part would not contain a lot of overhead. It would look something like this. (Hello world) PR NL (Another hello) PR showpage My next step is to fire up my old RPi and see what I can do with that. Can I configure it as a I2C slave and make it print a PostScript file transferred to it? I cannot say I have a lot of experience, but learning to do something new is half the fun. template.ps
  11. I've never looked closely on PostScript before, and I find it demanding but quite interesting. I think a PostScript based printing solution would work very well. As you may know, PostScript is just plain ASCII text which a X16 program could generate easily, send it to an RPi based printer adapter over I2C, which would send it to the actual printer. My initial attempt to write a PostScript "program" that handles line and page wrapping by itself is enclosed. I printed it with Ghostscript on MacOS to a PDF file with the following command: gs -sDEVICE=pdfwrite -o test.pdf test.ps test.ps
  12. That function is only supported in the Kernal master branch on Github, what is expected to become R39. BTW: I'm using a custom key handler in the X16 Edit pre-R39 version. It adds support for the END and DELETE keys and also the numerical keypad keys. That works very well, I would say. As you may see, the key handler is similar to a custom interrupt handler.
  13. The ESC/P (Epson) printer protocol is interesting for historical reasons, and supporting it might also make it easier to port programs made for other 8 bit platforms. It is, however, quite closely tied to functioning of dot matrix printers. Not everything makes sense on a laser printer, and you are also loosing some possibilities supported by a laser printer. I guess that's why Postscript was invented in the first place. If I was to design a printer solution, I would like to keep the options open, supporting more than one printing protocol/format, and making it expandable. To print an ESC/P byte stream, you would need to find or create a program that runs on the RPi and that converts the ESC/P input to Postscript or PDF. Making this from scratch is not an easy task. There are some open source alternatives available that I haven't yet tried. An example is found here: https://github.com/RWAP/PrinterToPDF/. If there is a ready-made conversion tool, implementing support for ESC/P would be very doable. Postscript input is easy to print from the RPi. But making your X16 program output raw Postscript might be too big of a challenge for most programmers. Having your X16 program outputting TeX or LaTeX is a lot easier than Postscript, and that has the benefit over ESC/P that you could use all features supported by a modern laser printer. And there are of coarse a multitude of other markup languages that could be used as the basis of a printing system.
  14. This thread is a bit old, but I've too been thinking about printer support. Being a complete novice on the matter, I would also believe that it's doable to write a driver that outputs PCL (or Postscript). Outputting plain text without a lot of formatting and other options might not even be hard. I don't know if it's true, but I would think that the biggest problem is how to transfer data to the non-vintage printers typically found in our homes today. The small HP LaserJet I have got at home only has an USB port as an example. As far as I can tell, you would need an "active adapter" between the X16 and the printer to solve this. Building this around a microcontroller such as the Arduino is probably very hard. You can find discussions online where people are trying to make Arduino based printer servers. I don't know if any of these attempts has been successful. The next level is something like a Raspberry Pi. You would then probably end up with a complete Linux OS on the Pi. The X16 could send PCL or Postscript data to the Pi (for instance over I2C), and the Pi could send it to the printer. The actual printing could be done by calling the Linux lp command. It might, however, be disturbing for some that this "adapter" is a lot more capable than the X16. We would need to hide the Pi in a nice box not to keep thinking about that Or are there any better ideas?
  15. Version 0.0.6 published now. This version makes BASLOAD + X16 Edit = True. As before, type SYS $9000 to load a BASIC source file. A new feature is that the program remembers the last loaded file, and you may select to reload that file without typing its name. Another new feature is that you by typing SYS $9003 may load and start the text editor X16 Edit. BASLOAD expects the X16 Edit executable to be stored in the root folder of the SD Card. The actual CBM DOS path is "//:X16EDIT*.PRG". If BASLOAD has been used to load a BASIC source file, that file is automatically opened in the editor. The purpose of these changes is to make the edit-save-load-test cycle more convenient. A more thorough description of the BASLOAD usage is found on Github: https://github.com/stefan-b-jakobsson/basload For an illustration of the BASLOAD+X16 Edit workflow, see the attached short video. BASLOAD workflow.mov
  16. @kliepatsch Debugging 6502 assembly can be quite hard. It would be interesting to hear what techniques are used by others. I usually do the following: I try to divide code into functions - the smaller the better - with well defined input and output. Test each function separately to ensure it works. Also test that functions work properly if the input is invalid. I think it's very valuable to comment what each step of the code is supposed to do. It helps you think more clearly about the code. Before using any tools to debug the code, I usually do the debugging in my head by just reading the code and thinking about what could go wrong. In most cases I find bugs with this method. If that is not successful, my next method is to store intermediate results/values in memory that I can look at after testing the function. This is often very helpful. I usually resort to the emulator's debugger as a last resort. Sometimes the debugger works great. But often I have a hard time making it work efficiently. Maybe I'm not using it right.
  17. Yes, it also supports the ON ... GOSUB N1, N2, ... construct.
  18. Published version 0.0.5 just now. This version adds support for BASIC source code in ISO mode lower case. On reading the source file, ISO mode lower case text is converted to upper case. The content of strings is, however, left untouched. This should make it possible to program conveniently in ISO mode as well. Apart from that a few bug fixes. The function that was reading the Kernal version number on startup was still not working properly in all circumstances, which caused some "random" loading failures. Available in the download section, and on Github.
  19. Yes, it's a clever solution.
  20. Your code should work. I made a simple test to enter a two line BASIC program, and then deleting the last line, and then another test to insert a new line in the middle of a program. I could not find a situation where the VARTAB pointer in $03e2 is not moved to the first address after the end of the program.
  21. That is understandable. I did the following to make a coming clean-up easy: The Kernal version is read at program startup. The control addresses for RAM and ROM select used by the detected Kernal version are stored in two zero page words In the rest of the program I read and store bank selections using these zero page words, like "STA (RAM_SEL)" When R39 is official, it's easy to do a project wide search and replace "(RAM_SEL)" with "RAM_SEL". RAM_SEL would then just be a definition pointing to the control address. But just a few minutes ago @Kevin Williams announced that prototype #3 is working more or less. Maybe R39 is not too long away...
  22. The Kernal version is stored in bank 0/$ff80. The problem is how to change to bank 0 before you know what version is running. There are several ways to handle this, I'm sure: Your solution might work. One possible problem is that there is a risk you are overwriting values used by the Kernal. Even if you could determine that $bfff is not used today it might be in the future. Another solution I've read about some time ago is to write a 0 both to $01 and to $9f60. This seems to work, but I'm not really a fan of doing this, as $9f60 is connected to VIA1 in R39 according to the PRG. Using the FETVEC function has the advantage that you are using a public Kernal function that should be stable between versions.
  23. Hi, I was struggling a bit with reading the Kernal version number in an assembly program that is to support both R38 and R39. As is apparent from the PRG, the Kernal version is stored in ROM bank 0/$ff80. The problem I had was that you are not in ROM bank 0 when starting an assembly program from BASIC. Reading $ff80 in the BASIC ROM bank does not give you the version number. And to change ROM bank you need to know what version is used. Almost like "catch 22". I found a solution using the Kernal function FETVEC ($ff74) that is callable from the BASIC ROM bank, getting the version number like this: lda #$80 sta $22 lda #$ff sta $23 ldx #$00 lda #$22 jsr $ff74 And then you have the version number in A.
  24. There are no guarantees, but VARTAB seems to be at $03E2 both in R38 and the upcoming R39. I would expect low RAM usage to be quite stable. "Non-public" KERNAL functions in ROM I expect to move around quite a lot between versions.
  25. Version 0.0.3 now published. It contains: performance improvements, support for ON ... GOTO N1, N2, N3 support for labels after THEN without preceding GOTO/GOSUB code cleanup Please let me know if you use it and find bugs.
  • Create New...

Important Information

Please review our Terms of Use