Jump to content
IGNORED

Happy driver pokey divisor 0


E474

Recommended Posts

2 hours ago, StickJock said:

I think that your second bcc to skip the other polarity (bcc bit6) should be a bcs.

Good catch! Indeed, it should read bcs in that code path. Can't update the post anymore...

 

2 hours ago, ijor said:

What were the exact frequencies you tried? If the device bitrate was slightly faster, it is possible that the extra stop bit compensated for the Pokey late capture issue. But not sure how the caps would make much of a difference at divisor zero.

I never went higher than the exact 125kbps an ATMega328 can deliver. I noticed that divisor 3 and lower did not work reliably at 8N1, but started to work when I switched to 8N2.

 

https://github.com/ivop/sio2world/blob/master/main.c

 

Line 251 and onward, including comment.

 

Link to comment
Share on other sites

51 minutes ago, ivop said:

Good catch! Indeed, it should read bcs in that code path. Can't update the post anymore...

 

I made a career out of assembly programming - BIOS at first and then a couple of decades of firmware.  I hadn't done any 6502 since 1990, though.  But anyway, code reviewing is second nature to me.  I like how you commented the cycle counts in the code, with taken/not taken for the branches, and noting the cycles for the different addressing modes.  In a past life, we would count instructions though entire code paths during the code reviews to ensure that it stayed below the cycle budget.  Hand-rolled multiplies, divides, square roots, oh my!  ?

 

For many years I worked on a micro that only had 2K of instruction ROM (and 128 words of RAM), so optimizing code was both necessary and a way of life.  If you could rework a routine to save an instruction or two, you were a hero.  After one particular code review, someone made the comment, "We saved a butt-load of instructions!"  We counted up the savings, and it turned out that we had saved 8 instructions (1/256ths of the ROM!).  From then on, we had deemed a new unit of measurement - the Firmware Butt-load, which equaled 8.  Half of a FW butt-load, 4, could also be called a FW cheek-load. ?

 

I'm retired now, and getting back into Atari & 6502 assembly.  And, of course, I'm annoyed at the "missing instructions", such as INC A. ?

 

 

  • Like 4
  • Haha 1
Link to comment
Share on other sites

Hi,

 

   Nice! That is much better code (IMHO) than mine! I don't understand the comment about rebuilding the tables for each track, unless some of the bits in PORTB_DATA are used for specifying the current track? Out of curiosity, which bit in PORTB_DATA is used for SIO (actually, does anyone have a description of which bits mean what, and maybe also for PORTA_DATA)?

 

   Presumably you could rebuld the tables with:

 

   LDY #0

   LDX #NEXT_TRACK_BITS + SET_BIT

LOOP

    LDA #NEXT_TRACK_BITS + CLEAR_BIT

    STA (ZTABLE),Y

    TXA

    INY

    STA (ZTABLE),Y

    INY

    BNE LOOP

  

   And modify the operand for the LDX and LDA per track, and ZTABLE for the bit table 0-7?

 

    I don't have access to my 8-bit kit at the moment, which is very annoying!

Link to comment
Share on other sites

1 hour ago, E474 said:

I don't understand the comment about rebuilding the tables for each track, unless some of the bits in PORTB_DATA are used for specifying the current track? Out of curiosity, which bit in PORTB_DATA is used for SIO (actually, does anyone have a description of which bits mean what, and maybe also for PORTA_DATA)?

 

Yes, the other output bits at the same PORT are used while seeking. They don't exactly set the current track, but they set the state of the 4 phase stepper which will change when you seek to a different track. The port map is available in several places including, of course, the schematics:

https://atariage.com/forums/topic/283585-1050-field-service-manual-51-page-version/?do=findComment&comment=4275240

 

The SIO output bit is at PB0.

Link to comment
Share on other sites

5 hours ago, ivop said:

I never went higher than the exact 125kbps an ATMega328 can deliver. I noticed that divisor 3 and lower did not work reliably at 8N1, but started to work when I switched to 8N2.

 

https://github.com/ivop/sio2world/blob/master/main.c

 

Interesting project. But I was asking about the exact frequencies when using divisors 0-3. I ask because it is very relevant if the UART frequency is slightly faster or slightly slower than the corresponding Pokey frequency.

 

If you used 125 Kbps for divisor zero, meaning slightly slower than nominal, that explains why it works at all. Being slightly slower compensates for the late Pokey capture. It would still be ideal to stretch the start bit a couple of microseconds, but of course, you can't do that with a standard UART.

 

I also assume that the frequency you use for divisor 3 (and probably for divisor 2 as well) is instead slightly faster than the Pokey one. And that might explain why you had to use two stop bits. Two stop bits might also compensate for the late capture. However, you should not need two stop bits for divisor zero because in that case the frequency you use is slower, not faster, and in that case two stop bits would not help.

 

Btw, I think you are rotating the bits the wrong direction. Bits are sent LSB first.

Edited by ijor
  • Like 1
Link to comment
Share on other sites

11 hours ago, ijor said:

I also assume that the frequency you use for divisor 3 (and probably for divisor 2 as well) is instead slightly faster than the Pokey one. And that might explain why you had to use two stop bits. Two stop bits might also compensate for the late capture. However, you should not need two stop bits for divisor zero because in that case the frequency you use is slower, not faster, and in that case two stop bits would not help.

 

This are the speeds the ATMega328 can generate when run at 16MHz:

 

div 0 - 125,000 bps

div 1 - 111,111 bps

div 2 - 100,000 bps

div 3 - 86,957 bps (PAL) 90,909 bps (NTSC)

 

11 hours ago, ijor said:

Btw, I think you are rotating the bits the wrong direction. Bits are sent LSB first.

I had planned to look that up, but forgot before posting. Change rol to ror :) 

  • Like 1
Link to comment
Share on other sites

Here's a table: (I suppose all ATMega328 based SIO devices use a similar table, although not sure if they differ for PAL and NTSC):

 

pokey-atmega.thumb.jpg.88df8276c59e7b3aa00f120b0b7a5a03.jpg

20 hours ago, ijor said:

I also assume that the frequency you use for divisor 3 (and probably for divisor 2 as well) is instead slightly faster than the Pokey one. And that might explain why you had to use two stop bits. Two stop bits might also compensate for the late capture. However, you should not need two stop bits for divisor zero because in that case the frequency you use is slower, not faster, and in that case two stop bits would not help.

Div 0,1 and 3 were slower. Div 2 was faster. I don't know why, but at 8N2 they worked. At 8N1 they stuttered.

 

pokey-atmega.ods

Edited by ivop
  • Like 3
Link to comment
Share on other sites

4 hours ago, ivop said:

Div 0,1 and 3 were slower. Div 2 was faster. I don't know why, but at 8N2 they worked. At 8N1 they stuttered.

Thanks for the info and the table. Interesting, and also a bit strange. This doesn't match my tests, although my tests were mostly with synchronous mode. The problem I found was only when transmitting faster than nominal, not at a slower bitrate. And the fix, again, was to extend the start bit, not the stop bit. I think Hias experience with his high speed SIO patch is similar to mine.

 

This certainly deserves more testing. Thanks again.

  • Like 1
Link to comment
Share on other sites

The new table (based on 600/800XL clock speeds) shows different errors now with proper clock speeds. Div 0 and 3 were slower, 1 and 2 were faster. With a 130XE the Pokey columns are different, too. For every 14.* MHz based Freddie machine.

PAL:  14.18757*1000000/8 = 1773446.250000
NTSC: 14.31818*1000000/8 = 1789772.500000

My "luck" with 8N2 was solely empirical. I have no logical explanation for it. I consider it letting Pokey catch its breath before starting again ;)

 

Edited by ivop
Link to comment
Share on other sites

Hi,

 

   I have the 51 page 1050 Field Service Manual - the schematic with the RIOT on it is on page 47. I'm not much of a hardware hacker, but it looks like RIOT pins 24 - 21 and 19 - 16 are mapped to PORTB, with the RIOT wired up as:

 

pin        Port B bit              Connected to

24         PB 0                     -> Data Out

23         PB 1                     <- VCC READY

22         PB 2                     -> NS04

21         PB 3                     -> NS03

19         PB 4                     -> NS02

18         PB 5                     -> NS01

17         PB 6                     <- Data In

16         PB 7                     <- CMD

 

I'm assuming that writing bits 1,6 and 7 don't matter (they are input values), but how exactly should bits 2,3,4 and 5 be set? I can't see how you can specify a track number (0 - 39, or 1 - 40) with only 4 bits, so how should you set these bits? 

Link to comment
Share on other sites

2 hours ago, E474 said:

I'm assuming that writing bits 1,6 and 7 don't matter (they are input values), but how exactly should bits 2,3,4 and 5 be set? I can't see how you can specify a track number (0 - 39, or 1 - 40) with only 4 bits, so how should you set these bits? 

D1/D6-D7 indeed won't matter since they're set as input pins.

 

D2-D5 control stepper motor phases. When the head needs to be moved or kept stable for reading/writing, all bits are 1 except the current phase, which holds the head in a specific placement. Walking that 0 bit one bit at a time in either direction then steps the head by a half track.

 

In terms of what you can write to those bits, energizing the wrong phase or more than one phase is probably not a good idea, leading to either head misalignment or drawing too much power. It might be safe to de-energize the phases by setting D2-D5 to inputs, in which case those bits could freely be written in the output register. However, doing that would require turning the stepper motor back on afterward and taking a 20ms head settling delay again before reading another sector.

 

Link to comment
Share on other sites

16 hours ago, phaeron said:

D2-D5 control stepper motor phases. When the head needs to be moved or kept stable for reading/writing, all bits are 1 except the current phase, which holds the head in a specific placement. Walking that 0 bit one bit at a time in either direction then steps the head by a half track.

 

In terms of what you can write to those bits, energizing the wrong phase or more than one phase is probably not a good idea, leading to either head misalignment or drawing too much power.

Just to add to this regarding bits 2,3,4,5 for stepper motor phase: The WST ROM sets 2 bits at a time, so two phases are engaged at a time "Full-step drive", which I learned results in a stronger "hold" but also puts the step position in between two phases, resulting in a 1/4 track misalignment if mismatching a ROM that uses only 1 bit at a time "Wave drive" (used with pretty much every other 1050 original or 3rd party firmware out there) as the WST mech would have been factory aligned according to the matching WST ROM stepper positions, and likewise Tandon mech to Tandon ROM.

 

Further reading: https://atariage.com/forums/topic/308399-1050-tandon-vs-the-other-mech/?do=findComment&comment=4573455

 

  • Like 1
Link to comment
Share on other sites

Hi,

 

    Thanks very much for the technical explanation - I think I understand it. Presumably the Happy would store the current value of these 4 bits in a variable somewhere, and then use them when it was transferring data to the 8-bit, so it should be in the code starting at $F000 (see https://github.com/e474/DUMP1050/wiki/Atari-Magazin-Happy-Programming-Course-Article-1) in the Happy ROM. I had thought the simplest way to handle high speed transfers would be to read from the track buffer (assuming it could co-exist with the 2K LUT and uploaded code), and use the Happy subroutines to read sectors and tracks into the Happy RAM. I think that is still a valid approach, provided I can dig out where the bit pattern is stored.

  • Like 1
Link to comment
Share on other sites

On 9/6/2020 at 8:36 PM, phaeron said:

It might be safe to de-energize the phases by setting D2-D5 to inputs, in which case those bits could freely be written in the output register.

If that would be safe it would be ideal because then no table would be required at all, and transmission could be easily performed at even just 6 cycles per bit. But I'm not completely sure it is safe. Have you seen any 1050 firmware that puts those signals in input mode?

 

I was trying to dig all the RIOT datasheets available. And it is not clear what is the exact behavior of the ports. Specifically, I don't know for sure if there is a pullup active when the signals are on input mode. Contrast with the PIA datasheets that do explicitly specify the pull up on PORTA but not on PORTB. If RIOT behaves like PIA, then the inputs on PORTB would be on high impedance. And as far as I can see at the 1050 schematics there aren't any external pullups at the board level neither for any of these signals. The signals are not connected directly to the stepper. They go through high current drivers that, again, as far as I can see on the datasheet, don't have internal pullups either.

 

So, this could mean that setting the signals as input might leave the input to the drivers floating and they might have unpredictable output behaviour. May be somebody with more knowledge of this kind of stuff can confirm this.

 

4 hours ago, E474 said:

Presumably the Happy would store the current value of these 4 bits in a variable somewhere, and then use them when it was transferring data to the 8-bit, so it should be in the code starting at $F000 (see https://github.com/e474/DUMP1050/wiki/Atari-Magazin-Happy-Programming-Course-Article-1) in the Happy ROM. I had thought the simplest way to handle high speed transfers would be to read from the track buffer (assuming it could co-exist with the 2K LUT and uploaded code), and use the Happy subroutines to read sectors and tracks into the Happy RAM. I think that is still a valid approach, provided I can dig out where the bit pattern is stored.

 

Not too difficult to find where the stepper phase is stored, but you don't actually need it. You can read the current state directly from the RIOT register.

 

I think that a single density track buffer would likely fit in RAM, but obviously a double density one will not. You have slightly less than 6K because the Happy ROM uses a couple of RAM pages for data and code.

Edited by ijor
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...