Saturday, 14 June 2025

What is (good) Art

 Intro

Although I am interested in Art and aim to like a wide variety, I often see Art which I don't think is very good.

This article provides some musings on the subject, many of which come from Wikipedia which I believe to be the fount of most knowledge (academics can be a bit sniffy about it).

Wiki

Wikipedia has an excellent article "Classifactory disputes about Art"

Ancient China had six arts  and the nine Muses embodied the Greek arts



The French generally recognise / classify 10 arts.  The first six are traditional with four newer ones developed over the last century.






A good starting point is whether to include Conceptual Art, immortalised by Marcel Duchamp's "Fountain", a mass-produced urinal.
Conceptual Art is "art in which the concepts or ideas involved in the work are prioritized equally to or more than traditional aesthetic, technical, and material concerns".
From my perspective I generally give this a big "NO". I believe art should offer more than this.

Below are provided some "notable" examples  and some more recent disputed works.



Definitions


Google AI provides a good starting point for what is art.

It also makes a good effort at describing Good Art

Good Art


Google AI definitions seem fine to me.

One "arty" definition which I have paraphrased is "art is what people who call themselves artists say they produce".
One could also try "art is what can potentially be bought and sold at art auctions".  Good art has a higher price / value.

The easiest way forward is to say that good art is what I like and to be prepared to say how much one likes it and why.

Some characteristics I try to include:

Can I see great technical skill in producing the work?
Is there a strong message being communicated by the work which I can detect?
Is it beautiful / enjoyable to experience?
Do I want to spend some time experiencing the work or seeing it repeatedly?
Does it stimulate me to think further on the subject?

I believe that covers it, surprisingly.



Monday, 2 June 2025

3D Printing : Platonic Solids

 Intro

I have previously been successful in defining a tetrahedron, the simplest 3D object, in STL.
Along the way I found that OpenSCAD is my preferred tool for creating STL files.  In OpenSCAD you can define a polyhedron in terms of its vertices and faces.  It is then a simple matter for SCAD to turn this into STL.  In fact I don't think I need to look at raw ASCII STL further because the SCAD "program" defines the object at a low level.

Following completion of a tetrahedron it makes sense to define the four other platonic solids in SCAD.
Wikipedia gives us a good start by defining vertex co-ordinates for the solids.

Octahedron

An octahedron has 6 vertices and 8 faces.  Armed with a suitable picture it is quite easy to label the vertices v0-v7.  I could then define three vertices for each visible face (in clockwise order, looking into the tetrahedron).  It was slightly harder to determine vertices for the hidden faces.  I wrote down the answer "looking through" the solid and reversed their order so they were clockwise.

I could then draw the octahedron in SCAD.  Although vertices are in the simplest form they do not provide a "flat-bottomed" object to print.  I struggled a bit then realised that I need two rotations for a flat-bottom.  Firstly 45 degrees around Z then, after a bit of trignonometry revision, 54.7 degrees around Y.

The result looks good and printed perfectly.




Icosahedron



I found good pictures for an icosahedron at sacred-geometry 

As usual work is required to define the faces which are not visible from the front. I started by creating a polyhedron with 5 trianglular faces touching point Z.  It was then an easy matter to go round the 10 triangles in the middle layer and 5 more to the bottom vertex.

The model produces needed to be rotated around the X-axis. The calculation for this is tan α = (φ-1/ φ) which gives a rotation 20.9052°



Cube

The cube is extremely simple to crate in SCAD and it doesn't require any rotation.  AS STL requires triangular faces the final ASCII STL output has 12 triangular faces instead of six squares.




Dodecahedron

I found it difficult to determine the vertices making up the six invisible faces of a dodecahedron even using the helpful diagrams.

Each time I worked out a face I added to the SCAD model so I could check it was correct and I gradually built up the final shape.  I could then work out the rotation (31.7 degrees) to give it a flag bottom and print it.

Outro

SCAD provides a great platform to build 3D polyhedra.  The Platonic solids all have convenient co-ordinates so most of the work involved in making the model is to determine which vertices make up each face.
I have noticed that others define their solids in SCAD in a different way, so I may investigate further.



Wednesday, 28 May 2025

MSBASIC : Control LCD

 Intro

We have implemented MSBASIC on BEN2, which is a 6502 system closely following Ben Eater's design.  MSBASIC was originally developed by Microsoft for the 6502 in 1976 and was implemented on many early and famous computers, including Apple and Commodore.  The software source was released some years ago and is available on Github.  It can be compiled for a variety of different machines.  Ben Eater has forked his own version which runs on his 6502 and mine!

Ben (me too) has an LCD display display on his 6502 and the generic MSBASIC doesn't include commands to use an LCD display.  Ben and has provided a video tutorial describing how to control the LCD using POKE/PEEK commands and he adds new MSBASIC commands allowing the user to "print" to an LCD.

As usual it is an interesting, educational tutorial allowing me to add LCD display into my MSBASIC.

POKE/PEEK

MSBASIC includes the commands PEEK and POKE to view (read) and update (write) specific actual memory locations.  We control LCD hardware by writing values to VIA (Versatile Interface Adapter) ports which are wired up to the LCD.  PORTB pins PB4-PB7 are used for data.  PORTA pins PA5-PA7 are used for control signals.

Ben uses different connections from VIA to LCD so I needed to work out how it should work BEN2.

So far we have done this in assembly programs by writing to the VIA ports we use at addresses $6000-$6003 (hexadecimal).
Similarly we can use POKE in BASIC programs to  write directly to VIA ports.  BASIC uses decimal address so $6000 equates to 24576.  By putting the data in 24576 = $6000 (PORTB) and changing control bits in 24577 = $6001 (PORTA) the character CHAR$ is displayed on the LCD.


We implement three principle BASIC subroutines using POKE commands: LCDINIT (set  up display) LCDPRINT (char display), LCDCMD (control command, clear screen, set cursor etc)
This subroutine shows that we can easily print a string on the LCD.


Add MSBASIC Commands

It is encouraging to know that we can control the LCD from MSBASIC.  It would be preferable to add some commands to the MSBASIC language so that we can easily initialise / control / display LCD output.  In his video Ben describes his detective work to add three such commands LCDINIT, LCDCMD and LCDPRINT to MSBASIC.  It turns out to be quite simple to add new commands and cause them to execute assembly subroutines.  Our own assembly code is stored in LCD.s and added in to the MSBASIC build.

For example, the LCDINIT command executes the code at label LCDINIT: in lcd.s.  This sets up the ports we need to use and calls LCD4_init which is my existing assembly code to initialise LCD.

Part of the detective work was to determine how MSBASIC passes arguments to assembly subroutine.  Ben looked at the PRINT command code and found that a subroutine GETBYT takes a value from the command line and stores it in the X-register.
So we can have a BASIC command "LCDPRINT 65" and the value 65 is passed to our LCDPRINT assembly subroutine in X-reg.  We then tell the subroutine to print what is in X-reg and prints the corresponding character "A".

I was very pleased that I could mainly cut and paste my assembly routines into lcd.s, rebuild MSBASIC and then see the code working.

Printing Strings

The MSBASIC PRINT command allows you to print characters strings of numeric expressions and Ben uses a follow-up video tutorial to show how he decoded the way in which the code (written by Bill Gates et al) works.  


One really cool idea is to display some of the MSBASIC internal variables addresses on the terminal then drop out of Basic to WOZMON..  You can then list out those addresses in WOZMON to find what values they are set as.  Ben uses this to understand how zero page memory is used to store characters, variables, strings, numbers and expressions for 

Armed with this knowledge the LCDPRINT subroutine can now print expressions and strings.  Ben provides a copy of his source on github and to make it work I simply had to swap in my own LCD subroutines, developed previously.
It worked without any quirky complications.


Outro

In the two MSBASIC tutorial implementing LCDs Ben has done a grand job discovering how the original code works, with some clever detective work along the way.  The tutorials are rather different from his usual approach of carefully reviewing data sheets and devising assembly code but interesting all the same.
It is rewarding to get the LCD working in BASIC as you can actually see the computer producing something rather than looking at a terminal emulator as usual.  The knowledge gained from this approach could be applied to add other hardware related functions if I feel like it.









































Thursday, 22 May 2025

Improving MSBASIC

Intro

Our 6502 Basic programming language implementation is quite comprehensive, but it does have some big problems.  In particular, since we didn't implement the LOAD and SAVE commands when setting up basic we have to start inputting lines of code from scratch each time we start MSBASIC.  Since BEN2 possesses no disk storage we cannot easily implement those commands.

A good, effective, convenient and practical workaround is to cut and paste programs from a PC editor into our terminal window.  This technique is ok for a single line of code but the MSBASIC program cant process larger chunks of code arriving quickly.
The first step in solving this problem, which Ben describes, is to receive characters into a 256 byte buffer, from which BASIC can read them at a more leisurely pace.
However, when reading in larger programs the 256 byte buffer fills up and characters are dropped.  To resolve this Ben implements RTS/CTS hardware flow control.  When the buffer is nearly full the 6502 sets the serial pin RTS low which causes the the terminal emulator to stop sending characters.  When the buffer is mostly empty the 6502 sets RTS high at which point more characters can be sent.

Ben explains how to implement these features in two videos How input buffering works and RS232 Flow Control.

Input Buffering

The original MSBASIC program uses a subroutine CHRIN to read characters in from the ACIA UART serial interface.  If no character is ready CHRIN waits until a key is pressed.  This works fine when a human (me) is typing on the keyboard as the program can process characters faster than I can type them.


We are going to create a buffer which will hold upto 256 characters which have been "pasted" into the terminal screen so that MSBASIC doesn't need to read them immediately.  Characters are placed in the buffer as soon as they arrive and are stored in the buffer at a location pointed to by WRITE_PTR, which is then incremented.  When MSBASIC needs to read  a character it uses the location pointed to by READ_PTR which is then incremented.  If READ_PTR=WRITE_PTR no character is available so the program waits.

We need to use an interrupt mechanism to help us with this.  The ACIA UART has an interrupt (pin 26) which we connect to the Interrupt (pin 4) on the 6502.  Now the 6502 interrupt pin will go high when a the ACIA has received a character.
In the 6502 software we enable interrupts and setup an interrupt vector at address 0xFFFE and 0xFFFF.
When an interrupt is received MSBASIC will jump to the interrupt vector address and run the interrupt service route to read in the character to the buffer.

On completion it will return from the interrupt to continue whatever program is running.
When MSBASIC needs to read character in we use a modified version of CHRIN.  First it calls a subroutine BUFFER_SIZE to see if there are any characters in the buffer, if not it waits for characters.
If characters are available CHRIN calls READ_BUFFER to get the next character and increment READ_PTR.

This mechanism works very nicely for small chunks of data pasted in to the terminal but fails if there are more than 256 bytes waiting.

The mechanism is called a circular buffer. The WRITE_PTR variable can take values from 0 to 255.  When the pointer is incremented from 255 it resets to 0 so the buffer wraps around.  Similarly READ_PTR "follows" it so the buffer continues to work.

When WOZMON, the monitor, starts we initialise the buffer so READ_PTR=WRITE_PTR and the bufer is empty before we enable interrupts. We must also use the modified CHRIN subroutine to read characters in from WOZMON to the buffer.

Flow Control

The RS232 protocol specifies wires in the cable to be used for flow control, the ones we will use are CTS/RTS.  On the PC end of the cable the serial driver looks at the CTS "Clear To Send" wire and if the voltage is set low the serial driver will not send any more characters until  the voltage is set high.  On the 6502 end the same wire is connected to RTS "Request to Send" (more appropriately "Ready for Receiving") which the 6502 will set low if it cant cope with any more characters.

Previously our serial UART only used four wires 5V, GND, RX, TX.  We need to make sure our RS232 cable or FTDI connector has six wires including CTS/RTS.  On the PC side the cable still plugs into a USB port.  On the 6502 side we connect a BLUE wire to RTS.

Now all we have to do is update our interrupt handler so that if the buffer is nearly full we set RTS low to stop communication.  When the buffer has plenty of space, set it high again.  In fact the ACIA RTS pin doesn't work very well so we use PORTA PA0 instead.


Lastly we need to tell PC terminal emulation software picocom or TeraTerm that it should use hardware flow control, otherwise the terminal emulator will just keep sending data.

It works, I can cut and paste a large BASIC program (say 500 lines) into the terminal window and it will be read in correctly, although it takes a few seconds.

Outro

Input buffering and flow control are vital but not very interesting.  It is pretty awesome how straightforward it is to program it on BEN2 with Bens help.  By implementing both buffering and flow control we have now written a proper serial driver on our 6502.
The benefits of this work are huge.  There is no way anyone would type a BASIC program in each time BEN2 was started up, but it isn't much work to spend a few seconds cutting and pasting a file before you start.



3D Printing : STL


Intro

I have started printing a variety of models on my Elegoo Neptune 3d printer.  3D models which I make using Tinkercad or are available at 3D websites are predominantly defined in the STL file format.  Once a suitable STL file has been created and saved the Cura app is used to "slice" them into layers and printing instructions are saved in TFT / gcode files which are sent to the printer.

STL stands for stereolithography but is better translated as "Standard Triangle Language". It makes 3D shapes by combining 2D triangles.  Curved surfaces are approximately with lots of triangles.  As you make the triangle smaller, you can make smoother surfaces at the expense of using more and more triangles.  Most STL files are in an unreadable binary format but ASCII STL is a valid alternative where points, polygons and surfaces are defined in a readable format.

It occurred to me that it should be interesting and straightforward to create simple ASCII STL models, e.g. for polyhedra.  In particular, the simplest polyhedron is a tetrahedron which comprises four vertices and four triangular edges.

Rules

The STL file format is very simple, you define a number of facets (i.e. triangular faces) each with three vertices.  You should also define a unit vector which is normal to the surface in the triangle.
A "solid" is made up of a set of facets.
There are some simple rules which are explained below:
1  The normal should be pointing outwards
2 Vertices should be listed anti-clockwise.
3 Each triangle should share two vertices
4 All vertices should be positive values.
5 values should be exponentials e.g. +2.00e03


It seems that, in practice, it is not necessary to follow all the rules.
As I want to read my STL files into Tinkercad or Cura I ignore any rules that they dont appear to require.

I didn't specify normal values as they are difficult to work out.
It appears that values dont have to be positive.
I used floating point or integers instead of exponentials.



Googling

I started by googling for ASCII STL examples but there don't appear to be many out there.  Florida State University have a Computational Geometry course, which contains a number of examples I may look at.


A couple of printables users Ambrosia and GaelLaFond provide details of STL tetrahedrons, including ASCII STL, which I will investigate further.


There seem to be a number of python apps which help with STL generation, Hand-and-Machine looks the best, it appears to generate various polyhedra in ASCII STL form.

A simple calculator for working out tetrahedron co-ordinates, an STL file viewer and some notes written by someone writing his own STL files from scratch may be useful.


As I hoped I came across an app, called OpenSCAD, which will be extremely helpful if I want to write STL to generate geometric shapes. Gael LaFond's tetrahedron was written in openscad as shown below.
There is a little quirk with OpenSCAD, in that it will only export ASCII STL files if you run it from the command line.  However, that isn't too much of a problem.



Tetrahedron

I have two possible files for my simplest possible STL object, from printables users Ambrosia and GaelLaFond . 

Ambrosia
Gael LaFond

Ambrosia's tetrahedron definition is very simple.  Normals are all set to zero, vertices are at unit addresses and are set as integers.
Unfortunately there is an error somewhere and I cant import the file into Tinkercad.
In contrast Gael LaFond provides a regular tetrahedron with all faces the same.  For a regular tetrahedron some of the vertices will always be at non-integer values.

I decided to make my simplest tetrahedron like Ambrosia's.
I started from Gael LaFond tetrahedron then changed the vertices to have unit co-ordinates and set normals to zero.







The result loads perfectly. We now have our simplest tetrahedron.  It isn't at all regular but it is very simple.  It has vertices (0,0,0), (1,0,0), (1,1,0), (1,1,1).
It is also very small as each co-ordinate is only 1 unit.  However choosing the units as inches makes it 25.4 times larger, alternatively it is easy to enlarge within Tinkercad.

I wanted to improve my design a bit. Firstly I wanted to make the tetrahedron with a right angle corner at the origin.  This has co-ordinates origin O(0,0,0), x-axis X(1,0,0), y-axis Y(0,1,0), z-axis Z(0,0,1).
I also found that the vertex command can have a description after it, so I added the vertex name after each.  This makes it easier to identify the order for the four facets (O,X,Z), (O,Y,X), (OZ,Y), (X,Y,Z).




Outro


It is interesting to understand how STL files are used to make up 3D objects and to be able to define them myself.  The files quickly become very complicated as they grow so a tetrahedron, as the simplest example is very instructive.  To me the hardest part is putting the vertices in anti-clockwise order when speciying triangular facets.  I suspect it would be very difficult to construct more than a few shapes manually.  I aim to be able to create more STL files using OpenSCAD, particularly poly


Thursday, 8 May 2025

MSBASIC for 6502

BASIC


The BASIC programming language plays an important part in computer history.  On early computers it was often the only high level language implemented and the only way of programming other than wrestling with the complexities of assembly language.

The Altair 8800 is widely accepted as the first Personal Computer, it was released in December 1974 and featured in Popular Electronics magazine in January 1975.  I have some recollection of reading about it at the time and wanting to buy one - although it would have been much too expensive for me and impractical to obtain one from America.


A couple of Harvard students, Bill Gates and Paul Allen, wrote a version of the BASIC language for the Altair and it became the first product of the company they formed called Microsoft.

To celebrate 50 years of Microsoft Bill Gates released the original BASIC source code 


Sometime later, when the IBM PC was released  in 1981, Microsoft won the contract to supply the PC DOS Operating System, and BASIC.
When I first used IBM PCs they contained no hard drive, just floppy disks.  If you forgot to put a floppy disk in the computer it would start running cassette basic.


I have known for some time that MSBASIC has been implemented in 6502 assembly language and it has been on my bucket list to try and get it working.  Luckily for me Ben Eater also decided to implement BASIC and he has provided a tutorial to show you how to do it on his 6502 system.  He also provides his assembly code version of MSBASIC to make it easy for us acolytes to follow in his footsteps.

Building MSBASIC for BEN2

The 6502 BASIC code is available on Github, and most of the files are 17 years old, reflecting the time when code was released to the public domain.
Rather unusually for Ben, he uses a trial and error method to build BASIC.   There are three main changes, the variables defined, character input and output, and memory configuration.  The Commodore Basic variables were used initally and adjusted to fit Ben's 6502.  We just have to provide our own I/O routines which are readily available and specify the details of our memory in eater.cfg.



Ben programs a ROM chip each time he modifies a program so he creates a 32KB image. My 6502 system usually has software loaded via the serial port so I dont have to remove/insert chips each time I make a change, since I find it incredibly tedious.
Unfortunately the BASIC program is about 9kB in size and much bigger than my usual programs.  My serial download program fell over so I had to revert to Bens ROM burning approach.

This required me to learn a little more about the assembler and linker utilities CA65 and LD65 so that I could choose where to locate BASIC in ROM.  Ben stores MSBASIC at the start of ROM address $8000 and the WOZMON monitor at $FE00 at the end of ROM.  I modified my system so that WOZMON could be stored at the end of ROM and BASIC is stored at $C000 in the middle.  This means I can still use my monitor MON5 at $A001 or the backup MON4 at $8001.


First startup of BASIC running on BEN2 felt awesome, suddenly we have a computer that is easy to write programs for.  Ben mentioned that there is a little "Easter egg" in the program.  When prompted for memory size, if you type "A", the names of the programmers "Weiland and Gates" are displayed.

So my last two projects have used source code written by Steve Wozniak, founder of Apple, and Bill Gates, founder of Microsoft.

As always there are some enhancements we need to make but this is definitely a leap forward.