2021-02-13 22:30 UTC
After completing the QSD/QSE module in part 4 I began working on the much needed filter module. Since I wanted my transceiver to cover more or less DC to 30MHz I needed quite a few band pass filters that could be switched in and out depending on the active operating frequency. I also wanted a modular design so that I could experiment with different filters without having to de-solder anything. To do this a decided to create a base module containing all the logic and switching circuitry and have all the filters as individual plugins. It would also be extra nice if all of this could fit inside the same RF-box dimensions as the QSD/QSE module. That way I could easily stack the modules in the final assembly. It also means at lot of filters in a small area. Hopefully I don't mess this up completely... After seeing how well the FST3253 performed in the QSD/QSE module I was curious to see how it would perform when using it as an RF switch for selecting the filters. The more common approach to this is to use relays or PIN diodes but there was no way I would be able to fit relays into such a tiny module and PIN diodes don't work very well at low frequencies (<1MHz), so the FST3253 suddenly became a very interesting option. This is the design I ended up with. In the middle are connectors for a total of eight filter plugins. I used four FST3253 switches. Two on each side of the filters. In theory I could probably make do with one on each side but doing it like this made the layout better and paralleling the switch banks in each FST3253 lowers the on-resistance. The control input to the module (SEL0-SEL2) is a 3-bit binary value (0-7) selecting one of the eight filters at a time. The external interface of the filter module follows the same design as the QSD/QSE module with two SMA connectors for the RF ports on one side and the power supply and control signals on the other. Opening the lid of the module reveals the filter plugins on top of the base board. A lot of things in a small space. Surface mounted components was more or less the only option. Removing the filter plugins shows the innards of the module. Here the layout mostly follows the layout of the schematic. I used strip board for alignment of the filter plugin sockets and plain copper board for the switches. Some extra isolation between the two sides. Don't know how much it actually helps but it can't hurt and keeps the cabling tidy. The control wires are super-glued to the center board to keep them in place. To get started I assembled a set of filter modules. They need some more work but performs well enough for testing. I probably should use double sided boards with more grounding to improve stop band performance. The filters right now are simple three pole designs using components I had available but there is room on the plugin boards for five poles and I definitely would like to improve these. The filters are not divided into HAM bands but in general segments without gaps. I like that design since it really makes it general coverage and still keeps the cross-over points out of the HAM bands. Eight filters covers the range up to 30MHz nicely but below 250kHz there may be need of some external filtering or at least a tuned antenna.
2020-10-30 13:37 UTC
For many years I have had an old Macintosh SE logic board that was scrapped out from an old Apple repair shop. Someone had broken the SIMM sockets at some point by snapping the retaining clips at the ends. A common problem unfortunately. I guess the repair shop didn't want to bother and just put it aside. When they eventually went out of business the board ended up in my hands. Besides the broken sockets it was in good condition and most importantly, no leaky battery damage. I have found no reliable way to repair SIMM sockets with snapped clips so I figured the best way would be to replace them. Some care must be taken while desoldering as usual but with patience and proper tools it's pretty straight forward. Apple used one pair of dual sockets meaning there are 60 pins to desolder for each. I did not have the exact same dual socket replacements but I did have single sockets. They are not as robust as their dual socket counterparts but since this Macintish SE board will be fully populated with its 4x1MB memory anyway I don't expect to replace the memory sticks very often, if ever. Now with the memory socket problem out of the way it was time for the next challenge.
How to test a compact Mac logic board with out the rest of the machineI have a few compact Macs including the Mac SE so I could potentially swap the boards around and test this out but I didn't want to disturb them and risk causing problems on working machines so I started playing with the idea of finding a way to use these boards without the matching CRT, analog board and power supply. This is something that I have wanted to try for a long time. The compact Mac SE design uses a single connector on the logic board for power supply and video output. This is the same type of Molex Micro-Fit connector commonly used today in modern PC power supplies but in the 2x7 pin configuration. I dug out the smallest spare ATX power supply I had and a new 2x7 Micro-Fit plug. I extracted the crimp terminals from the ATX 10x2 pin motherboard connector housing and re-arranged them into the 2x7 pin housing to match the Mac SE logic board connector. See the pinout in the schematic below. I removed all unneeded cables from the ATX power supply and hot-wired the power-on signal so that I could power on/off using the mains switch. The Macintosh SE logic board connector supply rails are +5V, -5V, +12V, -12V but the -5V is not used by the board itself and just routed through to the expansion slot. +12V and -12V are used for the serial port level drivers and audio amplifier. +12V is needed for the floppy drives. The connector also provides the video output divided into three different signals; vertical sync, horizontal sync and video pixel data. After double-checking and triple-checking and checking it all again a few times I powered up the board with meters on all supply rails and scope on the video/sync pins. All voltages looked good and I was happy to see a valid video signal being generated! Above is a picture of the power supply and wire harness along with the video adapter board I ended up building. The video output is at TTL level. The horizontal and vertical sync signals are active low and the video is inverted (low=white and high=black). The vertical frequency is a reasonable 60.15Hz but the horizontal frequency is a little unusual at 22.25kHz. I would place it somewhere between CGA and VGA. The horizontal signal is also unusually long and extends well into the visible area of the video lines. Not knowing exactly how to process this video I built a small adapter board containing an XOR gate for buffering as well as the possibility to invert all signals. The board also includes serial resistors for protection (don't want to accidentally fry any of the video output pins on the logic board!). For the final output I decided to use a standard 15 pin VGA connector with the R, G and B signals bridged to provide a B/W image. I figured it was the closest match and will make it easy to test on multi-sync monitors as well as one of the Swiss army knives of video, the Open Source Scan Converter. Here is a schematic over the completed video adapter based on the 74HCT86 XOR gate. I added some extra filtering on the supply as well as jumpers for selecting whether any of the signals should be inverted or not. The series resistors on the input is for protecting the outputs of the logic board and to reduce ringing on the signals. Same goes for the output side but here the series resistor of the video output is also needed to reduce the level a little bit closer to the VGA standard. Bridging the 75 Ohm R, G and B inputs of the VGA connector will present a 25 Ohm load and this in series with a 100 Ohm resistor will convert the 0-5V from the buffer down to 0-1V more suitable for a VGA input. In reality it should be 0-0.7V but it's close enough for B/W video (I don't expect the gate to reach full rail voltage either). The resistors on the TTL sync outputs will not affect the levels much but will provide some additional protection.
ResultsNot expecting any miracles, I started by connecting the board directly to my Dell U2410 monitor. As expected the result was underwhelming but at least the monitor did sync on the signal. The resolution and scaling was incorrectly detected which caused the vertical lines. Next I tried using the Open Source Scan Converter which did a much better job of dealing with the non-standard signal. If you do not know what the OSSC is then check it out here. It's basically a device that scales an analog video signal into a reasonably valid HDMI or DVI signal. Just what we need here. Using the OSSC the results was much better! The auto-detect did not detect the signal properly and needed a little help but after a little tweaking the picture was perfect. These are the OSSC parameters I used: - Horizontal sample rate = 704.00 - Horizontal sync length = 14 - Horizontal back porch = 164 - Horizontal active pixels = 512 - Vertical sync length = 1 - Vertical back porch = 26 - Vertical active pixels = 342 Another photo of the screen with OSSC scan lines added. Almost like sitting in front of a real compact Mac. A modern monitor with 16:10 aspect ratio is not too bad for this purpose actually since it is not that far from the aspect ratio of the compact Mac.
2022-08-28: Update for the Macintosh PlusWhen trying the same thing on a Macintosh Plus I could not get any monitor or the OSSC to sync on the output. On paper the specifications for the video on the Mac Plus is the same as for the Mac SE above so in theory it should have worked. This had me stumped for a while until I had a look at the vertical sync. The start of the Mac Plus vertical sync signal aligns with the Mac SE but it is ridiculously long. Over 20 lines! For comparison regular VGA, and the Mac SE, has a vertical sync signal that is around 4 lines long. I made another adapter specifically for the Mac Plus that incorporated an extra circuit to shorten the vertical sync signal. There was a free '86 gate available so I just used that as an inverter and then a simple RC filter. It worked really well and the OSSC can now lock onto the Mac Plus video signal without any issues.
2020-07-30 20:54 UTC
The world is in a weird state right now. I hope you are all doing well. For me this stay-at-home and work-from-home situation has at least given me some time to re-evaluate my shortwave transceiver project. To be honest I wasn't happy with the performance I got out of my superheterodyne design. It got more and more complex in order to achieve good performance across the intended shortwave range. It got complex to the point where I deviated far away from the goal of making a simple, understandable and yet decent performing transceiver out of common off-the-shelf parts. Either way I turned and twisted my design it ended up being too much of a compromise for my liking. This was not what I had in mind at all. Let's just say there is a reason good performing transceivers of this kind are expensive. Dealing with multi stage mixing and filtering is powerful but doing it right takes a lot of careful calculations and filtering. Also every stage of the transceiver also impose a risk of degrading the signal (i.e. by introducing noise and intermodulation) making each stage even more complex and critical. To reach my goal I had to find another way.
Direct conversionThe surprisingly good performance from my earlier experiment with the NE612 direct conversion receiver got me thinking. What if an advanced direct conversion design is actually less complex than a relatively simple superheterodyne design? Two common problems with direct conversion is carrier leakage and the ability to distinguish between upper and lower side band (since it's only a single conversion stage). Carrier leakage is a potential problem because the mixer is running at the operating frequency which can cause various issues as well as undesired radiation of a carrier signal even in receive mode. This can be mitigated by good RF isolation, careful mixer design and a receive pre-amplifier. Then there is the question about demodulation and modulation. A single mixer stage, as used in most simple direct conversion designs, will effectively act as a DSB receiver/transmitter with no way of distinguishing between upper and lower side band so we need something better. An answer to this is quadrature signals. This is achieved by using two mixers connected to the same RF-input. These two mixers are fed from a local oscillator that generates two signals with a very exact 90 degree phase offset, one for each mixer. This results in two mixing outputs. One in-phase signal, I, and one signal, Q, that is phase shifted 90 degrees. Having the I and Q signals and knowing the phase relationship between the two it's possible to determine the location of any given signal within the pass-band. Signals with exactly 90 degrees phase offset between I and Q belongs to one of the sidebands (+90 for one sideband and -90 for the other). This again is bidirectional and works for both demodulation and modulation. Diagram above shows a typical quadrature mixer which can be realized with a pair of double balanced mixers such as the SBL-1. This kind of mixers however are not ideal for this use-case. They are very sensitive to input and output termination which makes them complicated to use in a wideband scenario and the conversion loss is also relatively high. One very nice thing though is that the design can be made to be bidirectional making it possible to use the same mixer for both receive and transmit. The quadrature concept requires symmetry. Both mixers must be equal. Good off-the-shelf balanced mixers are also relatively expensive and the manufacturing tolerances are usually not good enough and will require matching of two mixers for good result. Lately there is a new way to do this that has become very common and that solves most of these issues.
Quadrature samplingThis principle is used in many software defined radios today. A good performing quadrature detector can be built using a modern digital multiplexer. After some initial testing I decided to give this a try. The principle is quite simple. There are four switches and four sampling capacitors. The detector cycles through all four switches in turn at a frequency that is four times the desired mixing frequency. That means that each switch is activated one time for every cycle which creates a 90 degree phase offset between each switch (360/4=90) and since there are four switches the frequency for which each switch is activated will be the desired switching frequency. The fact that there are now four outputs is very useful since the 0 and 180 outputs can be treated as a balanced I signal, and the 90 and 270 outputs can be treated as a balanced Q signal. The design can act both as a detector by feeding an RF signal into it and amplifying the balanced I and Q signals, or as an exciter of an RF signal by feeding it with balanced I and Q signals. Together, the system impedance, R, and the sampling capacitors, C, makes up a low pass filter. This determines the bandwidth of the detector and also causes the input impedance to peak at the center frequency and drop off towards either side. To some extent the "Q" factor of the filter will also vary with frequency.
My combined QSD/QSE moduleI wanted build a module that incorporated both a Quadrature Sampling Detector and a Quadrature Sampling Exciter into the same unit sharing the same RF input/output port and cover 0-30MHz. That way I could simply swap this module into my existing transceiver design replacing the first mixer, crystal filter, product detector, modulator, as well several amplifier stages. Actually just combining this module with a suitable band pass filter would make up a complete RF section of a low power transceiver. The QSD in itself is sensitive enough to perform well even without a preamplifier. Since the I and Q signals are balanced the common mode rejection is very good making it is possible to follow the detector by high-gain amplifiers. Below is a picture of the module that I came up with. As mentioned earlier and after some experimentation it became obvious that there was a lot to gain from RF isolation so I decided to build this module into a metal enclosure. I also sectioned off the inside of the module to further improve isolation. There are SMA connectors for RF input/output and local oscillator input. The TX/RX I/Q signals are fed through shielded microphone cables.
Design detailsThe module is divided into four compartments. - Top left: FST3253 switch and sampling capacitors - Bottom left: 74AC74 quadrature clock generator - Middle: 74HC4053 multiplexers for TX/RX switcing - Right: TL074 TX/RX I/Q amplifiers Update 2021-06-15 rev C: Moved Q_BAL to positive side of Q (90 deg instead of 270 deg). Does not affect performance but this way the calibration values makes more sense. Replaced TL074 opamps with the better performing NE5234. R26-R29 no longer needed. Fixed U5E flipped supply in schematic (thanks oz9ny!). See rev B. Update 2021-02-16 rev B: Moved R26-R29 so that they are shared for both TX and RX. See rev A. The schematic is laid out similar to the real layout. The front end of the module and mixer consists of the FST3253 switch. It is a common device to use for this purpose and is known to perform well. It is fast and has relatively low on-resistance. One minor downside is that it does not come in a DIP so in this case I use the SOIC version. It did not matter very much since this compartment is built in dead-bug style anyway to help with symmetry and RF performance. The four sampling capacitors (C5-C8) are soldered directly to the legs of the FST3253. I matched four out of a batch of 50 that came within 1% of each other. The quality of these capacitors are important. I used R82 polyester capacitors for this. The two switch banks of the FST3253 are connected in parallel to further decrease on-resistance and the input is biased (R4,R5) at Vcc/2=2.5V. Also there is a resistor, R3, in series with the RF input/output. Depending on the rest of the design this resistor may or may not be needed (keep in mind that resistance here increase noise and reduce gain) but it can be used to maintain 50 Ohm impedance. Preferably it should be left out but may be needed to play nice with other components. I measured the output impedance of my module and it ended up being closer to 35 Ohms so I set R3 to 15 Ohms. The FST3253 is driven by a quadrature clock that can be treated as grey-code to activate the switches one at a time in sequence. The quadrature clock is derived from an external local oscillator at four times the desired mixing frequency. One fast dual flip-flop 74AC74 is used to convert the incoming clock into two clocks at a quarter of the frequency but 90 degrees apart. To reach a 30MHz mixing frequency the external oscillator must be able to operate up to 30x4=120MHz. This means the faster 74AC74 must be used. Slower versions such as the 74HC74 or 74HCT74 will not work. Because of the high frequency this part is also built using dead-bug style. In-line with the quadrature outputs are 100 Ohm resistors (R6,R7). These resistors rounds off the signals slightly and reduces over tones. The resistors are actually placed right in the middle between the compartments to also act as feed-trough devices. The power supply to the 74AC74 is extra filtered (+5VD). Not because of any extreme demands from the 74AC74 but to prevent switching products to exit and reach other parts of the module. The middle compartment consists of the four "big" bipolar DC blocking capacitors (C15-C18) as well as the two 4053 multiplexers used for TX/RX switching. It also contains parts of the active balancing circuit but more on that later. The two 4053 switches the balanced I/Q signals from the FST3253 between the TX/RX I/Q amplifiers in the rightmost compartment. These amplifiers are based on TL074 operational amplifiers. There are better alternatives but I had these at hand and they performed reasonably well as a start. The most important thing is to maintain symmetry between the I and Q paths, therefore all of the resistors here have 1% tolerance or better. I actually used 0.1% precision resistors instead since that's what I had at hand. Update 2021-06-15: In revision C of the design I replaced the TL074 amplifiers with the better performing NE5234. They are drop-in replacements and provides better linearity, better sensitivity, higher output along with reduced distortion. About 10 times more expensive but definitely worth it.
Initial resultsTo test the module I used two signal generators and observed the mixing products on a scope. Example test setup: - LO = 28.000MHz 0dBm (Fluke 6060A) - RF = 7.001MHz -40bBm (HP 3325A) - I/Q signals hooked up to scope (Tektronix TDS2014C) in XY mode As you see here a 90 degree phase difference between the, in this case, 1kHz I and Q outputs generates a circle on the scope. This is what we want. The module was working! But it soon became apparent that more work was needed. Performance was inconsistent over the 0-30MHz operating range. The symmetry varied and in some parts, mainly over 25MHz, the dynamic range was noticeably limited. Also the carrier suppression was not good enough for my liking and varied a lot over the entire range (best 40dBc and worst 20dBc). This got me puzzled for quite some time until I started poking around with a high impedance high resolution volt meter directly at the sampling capacitors. What I found was that the DC levels varied with the local oscillator frequency and was never really equal and often far from the expected 2.5V they were biased at from the "front" side of the mixer. Now things started to make more sense. The question was what caused it and how to solve it.
Active balancingDisconnecting the DC blocking capacitors (C15-C18) thus isolating the detector from the rest of the circuit did not improve the situation. Even more careful matching of the sampling capacitors did however improve the balance problem a bit but not to the point that it was good enough. I was going to need something more than just well matched components. That's when I discovered that it was possible to bias the mixer from both sides by loosely injecting a DC voltage onto the I and Q signals, directly at the sampling capacitors. The bias compensation needed was still very frequency dependent but solved all of the problems, when adjusted properly. I added two filtered DC inputs to the module, I_BAL and Q_BAL, that connects directly to two of the sampling capacitors, one on the I side and one on the Q side. First I was afraid I would need four bias signals but it turned out that the over all I/Q balance is what matters so the DC offset can be injected to either one of the I and Q capacitors. Since the needed bias compensation varied with frequency I figured I could solve this in software by adding two DAC outputs to my Si5351 based local oscillator controller. I used a pair of PCF8591 8-bit DACs and by experimentally selecting values for R8-R11 it was possible to utilize the full range of the DACs which turned out to be more than enough resolution. These resistors along with the capacitors between them makes up a very important low-pass filter since these signals are injected directly into the signal path. I use a lookup table along with linear interpolation in software to generate the DAC values. Finding the correct values for I_BAL and Q_BAL is a matter of nulling out the carrier. As a start I adjusted these values for every even MHz within the operating range and interpolated between them. It turned out to work very well! Now the module performs very good from 0-30MHz with a carrier suppression of around 50dBc to 60dBc.
ConclusionThis has been a fun part of my transceiver project. Finally I feel that I have completed a central part of what I need to build the reasonable performing rig I initially set out to make. Initial testing by connecting the I/Q signals to a PC with SDR software worked surprisingly well and with very good band suppression. The next step is to construct a switchable band-pass filter module to go before the QSD/QSE module. Then there is the question of analog phase shifting networks for a fully analog approach but further experimentation will tell which way I will go.
2018-11-06 16:37 UTC
Yet again I feel like way to much time has passed since my latest project update. Or any update at all for that matter. This time I'm revisiting the world of early computing mass storage, namely, audio cassettes.
BackgroundMany of you probably have this love-hate relationship to data on audio cassettes. You know how unreliable and tediously slow it is but at the same time it has this cozy aura around it. I will never forget those times waiting half an hour for the program to load only to realize there was a load error and you had to do it all over again. Not to mention winding the tape back and forth according tho those hand written scrabbles and notes of various tape position values to find your precious data. Very hands on in a way modern computing rarely is today. I felt that my MC3 computer was missing out on a lot of fun so I decided to make an audio cassette interface for it.
Tapes and recordersData on audio tapes is nothing more than tones that the computer can generate and interpret when played back. The audio must be constrained to the limitations of the audio cassette and the recorder used. There are many variants here but I will focus on the, probably most common, Compact Audio Cassette format. There are different types of magnetic tapes in those cassettes that yields different frequency responses. Generally you have a usable response up to around 15kHz using a "normal" iron oxide tape. Chrome or metal tapes can have a frequency response of up to 20kHz when using good tapes and good recorder. Also cassettes made for shorter recording times are usually made out of thicker material thus making them more robust and perform slightly better. My goal is to store data using normal tapes together with a Panasonic RQ-2102 recorder. The RQ-2102 is a quite common recorder that has been in production for a long time and has historically been popular among computer users. It was even the recommended recorder by Woz himself for use together with the Apple I. I think I have the latest incarnation of the RQ-2102. It has changed appearance slightly during the years but the function and performance has been more or less the same as far as I know. Unfortunately the RQ-2102 is not equipped with a remote jack for controlling the motor from the computer which would be a nice feature to have but for my purposes it will do just fine.
HardwareThis is actually a very simple I/O card for my MC3 computer. There is a trade-off to be made here between hardware complexity, performance and flexibility. A complex interface that do most of the encoding and decoding in hardware will perform good but is most likely not very flexible. A simple interface, like the one I have here, do the encoding and decoding in software and because of that it is flexible and could, in theory, handle different encodings by using different software algorithms. Most home computers from the cassette era used simple bit-banged interfaces, just like this one, and software based encodings. That made it possible for users to develop custom loaders for example and exchange cassettes between different systems. My cassette interface is no more than a software controlled single bit I/O port and single bit ADC/DAC and the whole circuit fit on a small MC3 I/O board. The digital part of this board is not very exciting. It's just a '244 buffer (U3) for reading and a '374 latch (U4) for writing. That makes up 7 more bits than actually needed but they may come of use some day, who knows. By writing and toggling bit zero, an audio square wave can be generated and recorded on to the tape. A simple resistor divider brings the output level from the '374 down to microphone level for the tape recorder's input. Some experimenting may be required here to find a good level but in the schematic are the values that I found worked well for my RQ-2102. Reading back the waveform reliably from the recorder is a little bit more complicated. There is no guarantee that the shape and amplitude of the waveform is maintained during recording and playback. Therefore a bit of analog trickery is needed here to shape the incoming signal back into a logic level square wave that can be sampled by the '244 buffer input. I do this by using an LM358 op-amp (U2) connected as a comparator. The incoming signal is passed through a capacitor and biased at Vcc/2. The negative input of the op-amp is fixed at the same Vcc/2 and the positive input is fed the biased input from the recorder. This way, zero-crossings in the incoming signal are detected and converted to a logic level square wave that the '244 can pick up reliably. Because of the bit-banging and timing critical nature of this interface I also added an LED to show activity on the board since the CPU will most likely be too busy to write anything useful to the console during operation. An LED is a crude way to at least give some clue about what is going on.
Initial testingFirst off let me just explain why I choose to use bit zero for the output and bit seven for the input. The reasons for this is on the software side. Access to the interface must be made fast and efficient. Using bit zero for the output makes sense since bit zero of a register can quickly be toggled using a DEC or INC instruction. Similarly using bit seven for the input means that conditional branches can be made based on the bit value by using BMI and BPL instructions. These two tricks may seem insignificant but it can be a big advantage when timing is critical. To verify that the interface was in fact working I made a simple loop to mirror the input to the output.
casport equ $8060
loop ldaa casport
Bit seven is read and shifted around to bit zero and written back in an endless loop. By using a signal generator and oscilloscope I was able to verify that the circuit was working as intended.
Storing bitsWith the knowledge that the hardware side of the project was working I began tinkering with a simple low level format for data on tapes. Instead of trying to develop software to support an existing format I decided to start from scratch and make something of my own to cover the basics and to verify the concept. It's important to keep the signal moving in order to lock on to the data stream. Never let it be static for too long. I decided to go for an encoding scheme that uses one cycle per bit. There are many ways to accomplish this but I ended up implementing these three variants. 1. Frequency shifting One cycle of a high frequency represents "0" and a single cycle of low frequency represents "1". This effectively makes ones and zeros have different length. That means the average bit rate will vary depending on the distribution of ones and zeros. 2. Varying pulse lengths Here the cycles has been evened out to be the same length. The short cycle has been made longer and the longer cycle has been made shorter. The relationship between the high part and the low part of the cycle determines if represents "1" or "0". This makes the bit rate constant regardless of the content. 3. Combination of 1 and 2 In this case only the length of one half of the cycle determines the bit content. The average bit rate should be the highest of the three but still vary with the content, albeit to a lesser extent. With some clever coding I hope to support all three variants in the same loading routine.
StructureIn order to load data back from tape we need a way to locate the first bit of the first byte of the data stream. The software would need a specific synchronization pattern to look for. I decided to make it simple and use a synchronization pattern consisting of a relatively long sequence of consecutive ones followed by a single zero to indicate end of sync. Data is then followed directly after the sync. I decided to have one start bit for each byte and then the bytes are clocked out with the least significant bit first. The start bit has the value zero since the sync pattern is made up from ones. That way it's possible to indicate end of data by sending another sync pattern of ones. The start bit also gives some small level of phase error checking. A better way may be to also add a parity bit to every byte but I will leave that for another time. This is the final structure I ended up with:
1. Synchronization pattern consisting of 2048 bits "1" and one single bit "0"
2. Start bit "0"
3. Eight data bits, LSB first
4. Repeat 2 & 3 until end of data
5. Synchronization pattern again
By ending with an identical synchronization pattern as the one in the beginning it's possible to add several consecutive data segments but for now I will start with only one to keep it simple.
Software implementation of SAVE routineThe save routine is pretty strait forward. I created separate bit delay subroutines to make it possible to easily change the bit rate. There is a subroutine for generating the sync pattern and a subroutine for sending a single byte. Saving data is done in a simple loop until all bytes are saved. The routine implements variant number three (see above) where the length of the high portion of the cycle determines the bit value. I set the timing in a way that makes the a "1" bit have twice the length as a "0" bit. The save routine asks for a start address and an end address to select what data is to be stored on tape. Below is an example printout when running the program. User input in blue text.
> j a100
Start tape and press enter <CR>
This is what it sounds like: audio clip (watch your playback volume!)
Average data rate is around 255-300bps using this program. This could be improved with other timing parameters.
Download my experimental tape save routine:
Software implementation of LOAD routineThe load routine is a little more complicated. Care must be taken here to accommodate different timings and possibly different tape speeds and bit rates. My goal was to make it robust enough to automatically detect the bit rate and load data without requiring the user to set any additional parameters. The bit rate is determined by averaging the cycle time of the synchronization pattern. The core part of the load routine is this subroutine, "cycle", that measures the time of the high portion of a cycle.
bmi cycle3 ; if high on entry we are out of sync
beq cycle3 ; timeout
bpl cycle0 ; wait for positive flank
beq cycle3 ; timeout
bmi cycle1 ; wait for negative flank
The routine will return the time in A. When A is zero it indicates a timeout or that the routine was entered during a high portion of a cycle. This is used for error detection and to initially find and lock on to the synchronization pattern.
The program begins by asking where in memory to store the data from the tape.
When loading starts the program calls "cycle" repeatedly until a steady stream of cycles are found. That is detected when "cycle" returns a non zero value on every call. The first 256 steady cycles are used to determine the cycle time using a running average.
Knowing the cycle time for the sync portion means we know the cycle time for a "1" bit and from that a threshold value is calculated that sits between a "1" cycle time and a "0" cycle time.
Cycle time threshold value is the calculated using the formula: threshold = cycletime - cycletime/4. This is based on the assumption that the length of a "1" bit is twice the length of a "0" bit, thus this calculation places the threshold value right in between those values.
After the cycle time has been calculated the program monitors the stream to make sure there is no interruption. If the bit stream is interrupted the synchronization will restart from the beginning again. As soon as a cycle time corresponding to a "0" bit is found it marks the end of the synchronization and data will follow.
Data loading checks for a "0" start bit and receives eight bits and stores to memory. This is repeated until the start bit is not "0". This indicates either an error situation or that the ending synchronization has started.
Below is an example printout when running the program. User input in blue text.
> j a100
Press enter and start tape <CR>
Stop at 14FF
Download my experimental tape load routine:
Implementation for MCFS2Of course I couldn't resist making a few tools for my MCFS2 system as well. I created a simple checksum calculator also as a way to verify the tapes after load. casisave.asm - Cassette interface save (file to tape) - Syntax: casisave <filename> casiload.asm - Cassette interface load (tape to file) - Syntax: casiload <filename> chksum.asm - 16bit checksum calculator - Syntax: chksum <filename>
SummaryThese programs provide a relatively crude way of storing data on tapes but I think it's a good proof of concept. More work is needed to develop a proper format and error handling to make this usable in a real world scenario. Perhaps even a header with file meta data. That would be nice. This has been a fun project. It reminded me of time spent with the KIM-1 all those years ago. The reliability surprises me actually. No failed loads at all so far.
2018-02-17 15:22 UTC
I know these updates are far apart but the project is slowly progressing. This update is about two of the main boards of the transceiver. I decided to make this transceiver a modular design where functions are separated into modules that can be tested and verified separately. This makes it possible for me to experiment with different designs and improve the construction piece by piece. Lets bring back the original block diagram of the transceiver. The shadowed areas are the ones I'm describing here. Mixer and amplifier board on the left and product detector and modulator board on the right.[show older articles]