Friday, 20 October 2023

6502 : BEN2 : MON4 cutover

It was back in July when I last updated the monitor program which starts when the 6502 is booted. MON3 has proved to be very reliable, it has allowed me to forget about the details of downloading to RAM since it rarely goes wrong.  Restarting BEN2 also goes smoothly most of the time so I can concentrate on new developments.

New Functionality

Since then I have focussed mainly on adding VIA functions to the system. I started off with all 16 VIA pins on ports A and B in use: PA0-PA1 are wired for buttons, PA2-PA4 are LEDs, PA5-PA7 and PB0-PB7 are used for the LCD display. The first enhancement was to add a 74HC595 shift register, as described by Garth Wilson which uses only three pins, CA2, CB1, CB2 all of which are available.  It provides me with 8 extra pins and allows me to add an 8 LED bar (or 8 LEDs)  I can easily chain further shift registers if I need more output pins.



Next I followed Ben's advice on VIA interrupt functions; an Interrupt Service Routine and Interrupt Vector were initially set up to process a button interrupt on CA1.  At this stage I don't have anything specific which requires a button, so the ISR simply displays a letter on the screen.

VIA chips also provide two timers; I followed Ben’s tutorial to add a timer interrupt. Each 10ms timer  interrupt causes the ISR to increment a clock tick.  Using 100 ticks I can display a clock which increments each second.  I can also schedule regular events such as an LED flashing in the background.
To facilitate background activities we minimise code in the ISR and add an idle loop to the monitor which constitutes a simple state machine.  Whenever the monitor (or VIAtest) is waiting at the menu there is a check on the current tick count to determine whether other activities such as the LCD clock display or an LED flasher need updating.

The final major investigation was to add sound by setting up a buzzer.  It is a very easy addition, simply toggling an output pin with a speaker attached many times a second to generate a sound.  This exceeded expectations, the sounds are good and I can control VIA output to generate sounds of varying pitch.  This allowed me to play different notes, scales or tunes on BEN2, culminating in a rendition of three blind mice.

I still have a shortage of VIA pins so I changed over the LCD instructions from 8-pin to 4-pin.  The updates are quite straightforward.  Changing from 8-bit to 4-bit operation was a problem until I found it requires a magical reset sequence .  PB0-PB3 have now been freed up for other purposes.
At this stage I decided that I have plenty, maybe too many, changes for the current release and that I should leave hardware updates to the next release.

System Updates

Most of these changes don’t affect the monitor program itself, they provide extra or updated versions of subroutines used by other programs.  Since I bundle all ancillary subroutines with the monitor when I save it to ROM I can release them all together.  The monitor does need to be updated to include an ISR and to allow other processing to be carried out whilst waiting for user input.  It also includes a couple of extra menu options.  The “write byte” option has been added to update a single byte of ROM or RAM and I added an option to turn off interrupts when not required.

MON3 is stored at $A001 in ROM so I can save MON4 at $8001 and test in parallel, without destroying the ability to use MON3.

1 The write byte option has already been incorporated in the RAM development version of MON4 so I could write MON4 to ROM and I verified that it continued to work as expected.

2 I added the Interrupt Service Routine to MON4 at $8004 and set the reset vector at $FFFE-$FFFF to $8004 using "write_byte".  MON3 didn't use interrupts so this change didn't affect its operation.

3 I  have started to use Dirk Grappendorfs macros to save and restore A, X, Y registers on entry / exit to subroutines.  There is a convenient macro to load a 16-bit memory pointer.

4 I tried to rationalise zero page memory variables / usage.  I now have three 16-bit registers R0,R2 and R4 or alternatively six 8-bit registers R0, R1, R2, R3, R4, R5.  I setup local names within subroutines which can rename these page zero "registers" to be more meaningful in particular contexts.

5 Tests to terminal and shared routines were quite straightforward.  The main one was to add Binary Coded Decimal (BCD) conversion to SHARE.  BCD converts a binary number to a decimal one; Ben dedicated a whole video to setting it up so I expect to to be useful.

6 I added the button and timer interrupt routines to MON4, these are specific to the ISR so I keep them local to MON4.s rather than adding to shared routines.
Once I added interrupt processing other options (s-subroutine jump, x-xmodem download) stopped working  so I make sure that interrupts are turned off before moving to other programs.  

7 I added VIAtest subroutines for shift register processing to VIA.s

8 I added VIA Sound subroutines to VIA.s so that any program can play buzzers / musical notes.

9 I changed LCD operation over from 8-bit mode to 4-bit mode.

Once all functionality has been added I could change the reset vector from $A001 (MON3) to $8001 for MON4 using Write Byte.  We now have a new monitor.

Endnote

MON4 is another big step forward for my BEN2 6502 system.  Extra ports, interrupts, timers and sound are all significant useful additions.  The software changes are quite major and I aim to catch up with related hardware changes on the next release.  




Monday, 9 October 2023

Denon Receiver

Purchase

My existing HiFi comprising Amplifier, Tuner, CD player and speakers is at least 20 years old.  Sound has cut out on a couple of occasions and I am concerned that it will fail completely soon.
When it misbehaves I have investigated a replacement, and this time I decided to go ahead and buy a new Receiver (amplifier and tuner).  I am hoping that I can find a home for the old amplifier and tuner whilst it is still working.

The obvious place to go for hifi is Richer Sounds.  I have been buying equipment from them for over 30 years or more.  It is run by honest, helpful, knowledgeable people, often with many years service.  It has an excellent range of higi although now most sales are centred on TV and AV amplifiers.  There really is no viable alternative if you want to buy mid-range hifi.

My requirements are fairly simple, an amplifier+DAB Tuner, standard hifi size enclosure with plenty of inputs.  Connectivity should include bluetooth, airplay and NAS and it should be controllable through an app or Google Assistant.

The Denon DRA800H was a clear choice, having all the features I need at a price I expected.  More expensive models concentration on esoteric high-quality sound or home cinema capabilities.  Most of my music will come from mp3 files which wouldn't be enhanced by expensive audio and I wont have a TV incorporated.



I went along to Richer Sounds in Croydon, who validated my choice and showed me that it is the system they current use for audio within the shop. Paul, who advised and served me had been with Richer Sounds for 19 years.  I was in and out within 20 minutes with a box under my arm.

Setup

Basic hifi setup is, of course very straight forward.  I connected power, speakers, DAB/FM antenna,  CD player, Raspberry PI (RPI) audio and Pure Jongo phono inputs.

Next we connect to the network.  The Quick Install Guide gives you the option to use the TV to install but I declined this.  It then gives you the option to install using an iPad, which makes it very easy to select network and enter password.  I want external devices to switch on/off and control so I selected "NetCtrl:Always".

All the sources worked well, CD, RPI and Jongo behaved as expected; the DAB tuner cycles through stations as you would expect.

I also checked I could use my phone (by selecting Bluetooth on the remote), iPad (select Airplay on the iPad and Denon switches automatically to play), USB (by selecting USB on the remote).

There is a primitive web interface into the amplifier which I can access through the web browser by specifying the amp IP address as the URL.

Using the web interface, it is easy to change the name and source of each input to suit the actual connections and remove items that aren't being used.  In addition to the built-in tuner, my inputs are RPI (AMUSE), Pure Jongo (JONGO), Media Player (NAS, USB) and CD.  I also connected a HDMI to phono connection to HDMI 3 for a further phono input when I need it.
I can also adjust the levels of each input up or down so the sound from each is a similar volume.
I can also use the web interface to change the input source which is playing.

Apps

On the iPad I installed the Denon AVR Remote and HEOS apps which will be useful for me.

The Denon app has the same setup capabilities as the web interface for configuring the system.  Although its functions are rather limited you can additionally:
    turn the amp on/off
    select the input to play
    change the volume or mute sound
    change treble, base and balance
    choose 1 of the 4 "quick select" options
    easily switch to and fro with the HEOS app.
    set Tuner DAB channel presets

HEOS is used to select music to play on the amp.  Access is provided to commercial services which I dont really use, although Spotify, TuneIn and Amazon music may help me occassionally.
I can use HEOS to play music from my iPad, DLNA servers or a USB stick.
It is fairly typical of a music player app and will show you the current playlist from the chosen media.

Endnote

The primary purpose of my new receiver is to do what the old one does.  As expected it does that; my old Sony Amplifier / Tuner was a quality product and the Denon Receiver is similarly high spec.  In the past 20 years tech has provided extra interfaces and it delivers those as well, although they aren't very sophisticated - which is fine by me as the qualiry of the core product is most important. I am happy with what I have now.

There is some clever techy stuff still to come.  I aim to get Google Assistant on board so that I can use voice controls; I want to integrate Denon into my web app which I use to select and play music and I want to use a combination of Home Assistant and my ESP32 "button" to control the system.  



Monday, 2 October 2023

6502 : BEN2 : Sound

Theory

We already have a variety of uses for the 65C22 Versatile Interface Adapter outputs: LED, LCD, Shift Register/LED bar, interrupts/clock ticks.  We haven't previously provided any sound output and I was attracted to a brief article "Add sound to your 6502 for 10 cents and a speaker".
The article explains that all you have to do is connect a small 8 Ohm, 1 Watt speaker to VIA output pin PB7 in series with a 47uF capacitor and a 100 Ohm resistor.  You can then generate a square wave output from the VIA which translates to a sound of the corresponding frequency on the speaker.

Proof of Concept

 I don't have PB7 free at present so I will have to generate the wave form myself. I have recently attached a 74HC595 shift register (SR) to the VIA to provide extra outputs so I can easily use one of those outputs.

It occurred to me that my clock timer generates interrupts at 10ms intervals.  If I toggle an SR output in the interrupt service routine I generate a square wave output with period 20ms which will give me an output frequency of 1000/20  = 50 Hz.  This is the same frequency as mains hum so I should hear a low buzz from the speaker.

I connected up a little buzzer I had available (from my kit of 37, mainly useless, arduino peripherals) to a resistor, capacitor and SR output 0.  I added a couple of instructions to my interrupt service routine to toggle SR0 each time an interrupt is generated.  The test worked first time and I was able to hear a, rather quiet, low buzzing sound.  😀😀😀


The sound pitch is rather low for my liking, it is determined by the rate at which the timer generates interrupts.  If I decrease the period between interrupts, for example so that the period is 1ms, the pitch increases from 50Hz to 500Hz which is a lot better, it sounds approximately like middle C.  However an interrupt each millisecond only leaves 1000 cycles between interrupts for all interrupt processing, which may be limiting.

One positive aspect of using the ISR for sound generation is that programs can continue with other tasks whilst the sound continues.

For the next investigation I will setup sound as a general purpose subroutine which any program can call to leave a beep, buzz or ping.

Volume

The sound of the speaker is masked by other sounds in the room.  Although I dont want loud irritating sounds coming out of the buzzer I would like it to be somewhat more noticeable.  I tried two other speakers attached to the 6502, a 5cm 8 Ohm 1 Watt and a 1CM 8 Ohm, 0.5 watts.  The 5cm speaker was a bit louder and the 1cm speaker was quieter.

I also tried changing the 100 Ohm resistor value.  All three options were somewhat louder when there was no resistor in series.

I have a little PAM8403 5v, 3W+3W stereo amplifier, which I felt might resolve my issue.  It sometimes worked and made the sound louder and sometimes produced crackles.  I think the input voltage/current was too high causing it to mis-function.  I also tried to add a volume control to the amplifier input but it didn't seem to make a difference.  

It occured to me that if I need a small gain, of say 5, I should be able to make a simple transistor circuit to function as an amplifier, but I didn't feel like diverting myself to "analog" work.

It also occured to me that the shift register may not provide as much current output as the VIA so I changed my program to output to IVA pin PA1, which has a button attached.  The sound was a bit louder again so the VIA does provide a more power.

I believe I could get the amplifier working if I look into the hardware capabilities and voltage/currents in the circuit.  However, I decided, for the moment to stick with my 5cm speaker with no in-series resister and to utilise VIA output.  This combination provides an acceptable volume without making the system more complicated.

Sound Subroutine

 The sounds subroutine is simple.  An inner loop (lines 178-186 in the example below) is executed to toggle an LED bit.  A delay (mid_delay in the example below) is added into the loop to alter the sound frequency; a larger delay causes a lower frequency, no delay leads to the highest pitch.  The x register controls how many times the loop is executed, ie how long the sound is output for.


The sounds subroutine can be called with different values of A-reg for frequency and X-reg for duration.

At this stage I realised that higher notes sound quite musical so I may well be able to play simple tunes on the computer.

Tuning

It is common to denote musical notes in 8 octaves, each containing 8 notes.  Middle C is C4 and notes going upwards are C4, C#4, D4,D#4,E4,F4,F#4, G4, G#4, A4, A#4, B4, C5... This is slightly confusing.  Each octave has 12 notes, the 8 "white keys" and 5 sharp (#) "black keys" on the piano.
If music is played in the key of C major it doesn't need any sharps, other keys require sharps to make them sound right.
 The pitch (frequencies) of musical notes are related mathematically with the reference note being A4 (440Hz), If we can determine the parameters for one note (middle C, in my case) we can calculate appropriate values for other notes.

I found a convenient piano program webpage which allowed me to play notes.  I started by adjusting the A-reg value in my sounds subroutine until one sounded pretty much like middle C, I then calculated the frequencies and corresponding A-reg values for other notes.
Higher notes take less time to play so I also had to calculate durations for the X-reg values so that notes are all the same length.
This gave me a table of values for A-reg FREQUENCY and X-reg DURATION.  I added these a symbols in my program so that I can play notes easily.



Note Lengths

I can now play a sequence of notes and we have the beginnings of a tune.  The notes I chose were E4, D4, C4 which happen to be the first three notes of "three blind mice", and this has become my mission, to be able to play the nursery rhyme out of the computer speaker.

Notes have different lengths.  Having set up the durations shown above I judged that the shortest note that I can play is a semi-quaver which represents once round a loop.  Quavers, crotchets minims, ... require 2, 4, 8 iterations.

The notes sound a bit strange as there is no gap between them.  If you were pressing piano keys there would be a short lull between notes so I needed to add a gap.  I did this by making a delay based on 1/8th of each note, so a shorter note has a smaller gap after it.

I also tidied up my testing code a bit and renamed my subroutine from sounds to note as we are not playing a buzzer anymore we are playing music!

Three Blind Mice

We are now ready to play a tune.  I setup the notes as frequency, duration, length triplets in memory and provided a loop to load each triplet and play the corresponding note.  It actually sounds ok. 😀😀😀





End Note

This is excellent.  I started out wanting a simple buzzer and I have ended up with the ability to play nursery rhymes.  I have another type of output available.  It could be very useful during debugging as it is independent ot screen or LCD output.