This is a multi-part message in MIME format. ------=_NextPart_000_0018_01C9FB02.8D678D50 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Rikard Bosnjakovic wrote: > Now, the implementations I've read about is that the Amiga uses a PLL > to sync the floppy-reads. I have little knowledge of PLL:s, just a > vague theorethical hint of how they work, but since the clock stream > is not a plain "010101010101..." one I cannot think of a way to > determine how to implement this, or why. You don't need a PLL if you have a PIC, which back then they didn't have. I did a floppy drive emulator a bunch of years ago. At the time, the fastest PIC ran at 20MHz, meaning 5MHz instruction rate. That's not fast enough to decode MFM and then still do something meaningful with it. To get around this, I used a separate PIC as a MFM to synchronous data stream converter. The synchronous data stream was fed into the MSSP of the main controller PIC, which dealt with whole chunks of 8 half-bits at a time. That gave it just enough time to store them to a external memory and do the associated loop control and bookeeping. Today there are much faster PICs available, so you should be able to do some interpretation of the data on the fly. The concept of using a small PIC just as a synchronous data converter still makes sense though. Attached is the main module for this converter PIC. It should be useable on any 14 bit core PIC you can hang a 20MHz crystal on, like a 12F629 for example. It originally ran on a 16F628. > Half the bits (every second) need to get ridden of. Not quite. There are special cases (at the beginning of sectors if I remember right) where the normal MFM scheme is violated. You do have to look at each half bit to interpret the stream, even though most of the time two half bits will simply make a single data bit. ------=_NextPart_000_0018_01C9FB02.8D678D50 Content-Type: application/octet-stream; name="flw_main.aspic" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="flw_main.aspic" ; This module contains the main application routine that is run after ; the system is initialized. ; ; This firmware is very specific to its small tasks, and deviates from ; the Embed Inc "standard" structure for PIC firmware. This firmware ; translates the asynchronous MFM write bit stream to a synchronous = bit ; stream (clock + data) to be received by the synchronous serial port ; hardware of the main floppy emulator controller. See the FLOPPY_FLW ; documentation file for more details on the MFM data stream. ; ; The incoming MFM data line is tied to the RB0 input, which produces ; an interrupt on the leading (falling) edge of each MFM pulse. This ; interrupt is not handled in the usual way, but is used as an = externally ; forced GOTO 4. The interrupt routine never returns to the = interrupted ; code. Execution restarts at the interrupt vector (location 4) at = the ; start of each MFM pulse. A single 0 bit is emitted for each input ; pulse, followed by a 1 bit for each following 1/2 MFM cell time that ; does not contain a pulse. The code at the interrupt vector = therefore ; produces this single 0 bit, then successive 1 bits. This process ; is automatically restarted when the next incoming MFM pulse is ; received. ; ; The main control processor only releases this processor from reset ; when MFM pulses are to be converted. All lines go to high impedence ; when reset is asserted, so this processor is essentially not present ; except during floppy write operations. ; include "flw.inc" main code ; ;*********************************************************************** ; ; Routine MAIN ; ; This entry point is jumped to from the INIT module, once system ; initialization is complete. ; glbent main ; ; Initialize the interrupt system. Set up interrupts on the falling ; edge of RB0. The interrupt system has already been initialized to ; off by the startup code (STRT module). ; dbankif option_reg bcf option_reg, intedg ;select falling edge for RB0 = interrupt ; ; Initialize the clock and data output lines. The data line idle ; state is high. A low data bit indicates an MFM pulse was received. ; The data line is sampled on the falling edge of the clock line. ; ; This section also sets the direct register bank for access to the ; clock and data lines, which must be in the same register. ; dbankif clk_reg bsf clk_pin ;init clock out to high (idle) bsf dat_pin ;init data out to high (idle) ; ; Pre-load W with the value to reset PORTA to at the start of an = interrupt. ; This will be the data line low and the clock line high. ; movlw (0 << dat_bit) | (1 << clk_bit) ; ; Enable interrupts and enter the idle loop. ; bcf intcon, intf ;clear any existing interrupt condition bsf intcon, inte ;enable RB0 edge interrupt bsf intcon, gie ;enable interrupts globally goto idle ;go continuously emit 1 bits until next = input pulse ; ;*********************************************************************** ; ; Interrupt routine. The processor effectively performs a CALL to ; this location on an interrupt, which in this case is a falling edge ; on the MFM input line (RB0). ; ; This interrupt never returns to the interrupted code, so it is used ; here as an externally forced GOTO to a known address. The call = stack ; will overflow, but is of no consequence because no RETURN is = executed. ; ; Each MFM bit cell is 2uS long, which is 10 instructions in this ; code. We must therefore emit a synchronous output bit every 5 ; instructions. The first one is 0 indicating an MFM pulse, and ; the remaining bits will be 1 (the idle state) until a new MFM pulse ; is received. ; ; MFM pulses never occur in adjacent 1/2 MFM cells. This means ; there are at least 10 cycles after one pulse before the next. (A ; little less actually due to write pre-compensation done in the ; floppy controller to compensate for how flux transitions "wander" ; on the magnetic media). ; intsvc code 4 ;interrupt vector ; ; Two cycles are lost due to the interrupt mechanism. W contains the ; output port register value for data low, clock high. ; bcf intcon, intf ;clear the interrupt condition bsf intcon, gie ;re-enable interrupts movwf clk_reg ;set data low, clock high bcf clk_pin ;send the 0 bit to indicate an MFM pulse comf clk_reg ;flip from data 0 clock 0 to data 1 clock 1 = (idle) bcf clk_pin ;send the first 1 bit bsf clk_pin ;reset the clock line nop ; ; 10 cycles since pulse. ; nop nop bcf clk_pin ;send a 1 (idle state) bit bsf clk_pin nop ; ; 15 cycles since the pulse. So far a 0 followed by two 1 bits have ; been sent, representing 3 MFM 1/2 bit cells. From now on we ; continue to emit 1 bits indefinitely for every 1/2 MFM bit cell. = This ; process will be automatically aborted and execution resumed at the ; interrupt vector when the next MFM pulse is received. ; ; A single bit must be emitted every 5 instructions, starting in three ; instructions. The 5 instructions above could have been performed ; by the code below, but were written separately to make it clear ; what the code below is supposed to do indefinitely. Note that a ; GOTO uses two cycles, which is why it jumps one instruction ; into the sequence. ; nop idle ;loop back here indefinitely until next MFM = pulse nop bcf clk_pin ;send a 1 (idle state) bit bsf clk_pin goto idle ;uses two cycles to repeat at IDLE end ------=_NextPart_000_0018_01C9FB02.8D678D50 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist ------=_NextPart_000_0018_01C9FB02.8D678D50-- ******************************************************************** Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products (978) 742-9014. Gold level PIC consultants since 2000.