It is currently Mon Oct 20, 2014 4:48 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 9 posts ] 
Author Message
PostPosted: Tue Feb 28, 2012 3:43 pm 
Offline
 Profile

Joined: Fri Nov 07, 2008 2:28 pm
Posts: 65
Hi,

So how do you program sounds direct to the Hardware.

I guess I would lose envelope support but I reckon I could write something myself - and it would also free up page 8 for my own use.

I've been trying to finish a mini-game I've been working on which is a Mode2 side scroller and I've been finding when I exceed a frame the displays gets all corrupted. (Probably because the screen scrolls too far and doesn't get deleted at the edge.)

Anyway - time is very important - RTW's hardware keyscan code made a great difference so I was thinking replacing the OSWORD sound calls I make would make a difference as well - I'm right on the edge of the 50th and I'm playing 2 track music. In fact if you press loads of keys simultaneously it frames-out so I'm thinking the system IRQ handler (which I pass on to) is up to something and I'd like to get rid of it.

I discovered reading FE45 gives me a clock I can time code with like this:

Code:
LDA   &FE45
STA   clk1
JSR  _MAINLOOP
LDA   &FE45
STA   clk2


When it gets to $1A I'm out of time.

Following on from sound I guess it would would useful to know how to read the joystick and set the palette in Hardware as well - I think that would just about cover everything!

- PJ


Top
 
PostPosted: Tue Feb 28, 2012 9:22 pm 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 6:46 pm
Posts: 380
Location: Málaga, Spain
I don't have time to go into much detail now, but just to say that if you need the extra speed push, then getting rid of the OS IRQ handler is certainly the way to go.

Writing your own sound handler is not really tricky, but be warned that the code and related tables will certainly take up more space than you would save by freeing up page 8.

Prettty much everything you need to know about programming the sound chip is in the AUG at page 419 onwards. Note that it's addressed via the System VIA Port A (&FE41/&FE4F) along with the keyboard, so you have to disable the keyboard by writing 11 to &FE40 before doing the sound chip writes.

Have a look at my Blurp blog entry on sound - http://www.retrosoftware.co.uk/wiki/ind ... ry20101102 - and the old forum post of mine that I linked to, which might help a bit. When I have more time, I can try to expand on some of this, but it's quite a big topic which can hardly be done justice in a small reply...


Top
 
PostPosted: Wed Feb 29, 2012 4:58 pm 
Offline
 Profile

Joined: Fri Nov 07, 2008 2:28 pm
Posts: 65
Hi,

Thanks for that - I now have music playing direct to the hardware and cycles to spare!

That saved the day.


Here's my code - I'd appreciate any comments:
Code:
.freq_sel:      EQUB &E0,&C0,&A0,&80
.volume_sel:   EQUB &F0,&D0,&B0,&90

;
;
;   X - midi note
;   Y - channel
;
._MAKE_SOUND_HW:
      SEI
      ; Set all portA bits as output
         LDA    #&FF
      STA    &FE43

      ; channel select + freq low
        LDA   midi2bbc_low,X
      ORA   freq_sel,Y
        JSR   _DIRECT0

      ; freq high
      LDA   midi2bbc_high,X
        JSR   _DIRECT0

      ; channel + volume
        LDA   volume_sel,Y
        JSR   _DIRECT0

      CLI
      RTS



._DIRECT0:       STA   &FE41     ;set volume or frequency in DataPort A

           LDA   #0
           STA   &FE40   ;\Output register B
           NOP
           NOP
           NOP
           NOP
           LDA   #8
           STA   &FE40   ;\Output register B

         RTS


The midi2bbc tables are based on:

table = 4,000,000 / (32 * frequency)

low is value&15 and high is value>>4

The codes based on the AUG example.

I'm not sure why I have to toggle a bit on $FE40 but it doesn't seem to work without it.

I didn't seem to need to do:

Code:
   LDA #11  ;(that 11 is decimal isn't it?)
         STA   $FE40


Just need to make some envelope type control now...

-PJ


Top
 
PostPosted: Wed Feb 29, 2012 5:12 pm 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 6:46 pm
Posts: 380
Location: Málaga, Spain
Yep, that looks fine. I'd be inclined to add an extra NOP between pulling the sound enable low and high, to guarantee that 16us passes ok. As for why it's necessary, Tom Walker once told me the reason:
Tom Walker wrote:
Internally the SN chip divides the incoming clock (4mhz) by 32, which it then uses to clock everything else. I guess it only checks the write signal for a high->low transition at one point (presumably the beginning), so you need to hold it for a whole 32 cycles (16 from the 6502 point of view) to ensure it actually sees it.
So now we know.

It's only necessary to set keyboard enable high (by writing &0B to &FE40) if you've previously pulled it low (by writing &03 to &FE40) in order to read keys. If you do that anyway after checking for keypresses, all will be well.

Be careful if you're handling sound inside an interrupt routine though, because if your key checking code is interrupted, this will screw up. Two solutions: either disable interrupts around your key checking code, or (better), move your key checking code into the VSync interrupt and have it set bits in a location which can be polled in your main loop. The advantage of this approach is also that your interrupt routine can put the results of the joystick control into the same bits, and so your main loop will get joystick control "for free".


Top
 
PostPosted: Wed Feb 29, 2012 5:38 pm 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 6:46 pm
Posts: 380
Location: Málaga, Spain
Joystick control by direct hardware access is a bit of a pain by the way. Main problem is that the ADC hardware lives in a different location on BBCs and Masters, so you'll have to take that into account, depending on the results of OSBYTE 0.

The joystick fire button is easy: this just comes from bit 4 of &FE40 (remembering to configure bits 4-7 as read bits by writing &0F to &FE42).

Reading the joystick direction is a bit more involved. You have to set off two ADC conversions, one on channel 0 (X direction) and the other on channel 1 (Y direction). If you do this in 8 bit mode, the results will arrive more quickly.

Here's how Blurp does it (I assemble &FEC0 as the address of the ADC, like a BBC B, and self-modify this to &FE18 at startup if it's running on a Master):

At initialisation time (once only):

1) turn off interrupts
2) poll bit 6 of FEC0 and wait for it to be clear (this signifies that an ADC conversion is already in process - you want to ignore the interrupt that this would generate, and as far as I know, there's no way to abort/cancel the conversion).
3) write &10 to &FE4D to clear the ADC interrupt flag
4) write &90 to &FE4E to enable ADC interrupts

In the VSync IRQ handler:

1) Poll joystick button. If pressed (bit 4 of FE40 clear), this means that a joystick is connected (force the fire button to be pressed by insisting on "Press SPACE or FIRE" to begin :) Flag somewhere that a joystick is connected.
2) If a joystick is connected, write 0 to &FEC0. This sets off an ADC conversion on channel 0 with 8-bit precision. When the conversion is finished, an interrupt will be generated which you can check at the beginning of your handler.

In the ADC IRQ handler:

1) Acknowledge the ADC IRQ by reading from &FE40 and throwing away the result.
2) Load &FEC0. Bit 0 tells us if the result is from ADC channel 0 or 1.
3) If it's channel 0, then bits 4-5 tell us whether the joystick is left, centred or right:
Code:
00 = right (I think)
11 = left
01 or 10 = centred.
Then write 1 to &FEC0 to start an ADC conversion on channel 1.
4) If it's channel 1, then read bits 4-5 to tell whether the joystick is up, centred or down.

Bit of a brisk overview but hopefully you get the idea.

Incidentally, even if you're doing it OS-legally, there are some things you can do to get slightly better performance:
OSBYTE 16 with X=2 will ensure that only 1 joystick is polled
OSBYTE 190 with X=8 will do 8 bit conversion which is much quicker.


Top
 
PostPosted: Sun Apr 01, 2012 3:16 pm 
Offline
 Profile

Joined: Fri Nov 07, 2008 2:28 pm
Posts: 65
So.... I finally got round to running the direct sound access code on a real BBC (a master) and would you believe it but it doesn't work. Even worse it works fine in the emulators but not on the real thing.

I've been hammering away at it for more than a day now and can't solve it.... it seems like if I change the frequency and volume at the same time the sound chip only picks up the last thing I do.

Also it seems to prefer it if I do it in the Interrupt and not outside. (Even with SEI/CLI covering the code).

I even checked the OS disassembly to see what that's doing and changed my access code to what they are using:


Code:
._DIRECT1:
  ;;   SEI
     STY     tempyy
     LDY     #&FF    ;System VIA port A all outputs
     STY     &FE43   ;set
     STA     &FE4F   ;output A on port A
     INY             ;Y=0
     STY     &FE40   ;enable sound chip
     LDY     #&02    ;set and
 .rloopa:
     DEY             ;execute short delay
     BNE     rloopa
     LDY     #&08    ;then disable sound chip again
     STY     &FE40   ;
     LDY     #&04    ;set delay
 .rloopb:
     DEY             ;and loop delay
     BNE     rloopb
     LDY     tempyy
 ;;    CLI
     RTS             ;and exit


 


I notice they use $FE4F instead of $FE41 - I'm not sure what the difference is there.


My setting code is like follows:


Code:
   LDA volumea
   ORA    #&90
   JSR   _DIRECT1


   LDX    freqa
   LDA    Midi2bbc_low,X
   ORA    #&80
   JSR   _DIRECT1
   LDA    Midi2bbc_high,X
   JSR   _DIRECT1



...similarly for the other two channels.


The only other thing I've tried is adding this at the top

Code:
LDA #&0F
STA &FE42


to write enable the latch register at $FE40


Top
 
PostPosted: Sun Apr 01, 2012 6:16 pm 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 6:46 pm
Posts: 380
Location: Málaga, Spain
If you have the keyboard enabled for reading, make sure to disable it before writing to the sound chip, with

Code:
LDA #15
STA &FE42
LDA #11
STA &FE40


Top
 
PostPosted: Sun Apr 01, 2012 6:35 pm 
Offline
 Profile

Joined: Fri Nov 07, 2008 2:28 pm
Posts: 65
Man ..... Thanks! Thanks! Thanks!

It work's perfectly now - I was totally stuffed before - didn't have a clue what was wrong... so frustrating - so I wonder what's wrong with B-em and Beebem?

I if ever finish my project (which is a lot closer to being finished now...) they can be tested with my disk.

Thanks again - I'm sooo happy.

- PJ


Top
 
PostPosted: Sun Apr 01, 2012 8:59 pm 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 7:02 pm
Posts: 273
PitfallJ wrote:
so I wonder what's wrong with B-em and Beebem?


Neither currently emulate contention on the slow data bus. What causes the issue is that the System VIA is trying to drive the bus with the sound data, but the keyboard is also driving it with that data. The result is a mess.

The in-progress B-em v2.2 does emulate contention, and hence this fails like on a real beeb!


Top
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron