6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 15, 2024 8:29 am

All times are UTC




Post new topic Reply to topic  [ 13 posts ] 
Author Message
PostPosted: Thu Dec 02, 2004 6:16 pm 
Offline

Joined: Thu Dec 02, 2004 6:03 pm
Posts: 3
Im working on a project that uses a 6522 VIA to create a square wave.

I have been told by setting the shift register on the via to 10101010 i can generate a continous square wave on the CB2 pin. However i am having trouble and my program does not seem to work.

i have come accross limited resources documenting this feature and all i have seen is that i should set bits 2-4 as 100 of ACR

Code:
LDA #$08
STA $A00B
is this right?

Apparently, by changing the values in timer 2, the rate at which the shifting is done should change:

Code:
LDA #$C6
STA $A008
LDA #$01
STA A009


Im not entirely certain if this is true or not!
Also do i need to set port B as an output or is this done automatically?

hopefuly then by connecting a speaker through a capacitor to CB2 this code will make a note

Any help really is GREATLY appreciated.




Code below!


Code:
SETVAL:   SET TEMPY=$00
   SET TEMPX=$00
   SET PAUSEX=$50      ;PAUSEX/Y set to 50k cycles
   SET PAUSEY=$C3
   SET NOTENUM=$00      ;note number - next note to play - 00=start
   ORG $F800

SETCB2:   LDA #$FF
   STA $A002   ; set port B (CB2) as output

SRSET:   LDA #$99      ; 10101010 goes into
   STA $A00A   ; shift register to be looped = pulse

TMRSET:   LDA#$08            ; set shift reg to timer2 mode - timer 2 is then set to cont mode
   STA $A00B


PLAY :   LDY NOTENUM      ; what note to play next
   LDX TUNE,Y      ; loads note number X from NOTES
   INY         ;increment note number
   STY NOTENUM           ;store next note
   CPX #$01      ; check value from memory and play corresponding note
   BEQ NOTEA
   CPX #$02
   BEQ NOTEB
   CPX #$03
   BEQ NOTEC
   CPX #$04
   BEQ NOTEC
   CPX #$05
   BEQ NOTED
   CPX #$06
   BEQ NOTEE
   CPX #$07
   BEQ NOTEF
   CPX #$08
   BEQ NOTEG
   CPX #$FF      ; FF symbolises end of tune
   BEQ ENDJUMP



   JSR WAIT
   
   
   JMP PLAY   ; jump back up to play next note
   
ENDJUMP: JMP TMRSTP


WAIT:   STX TEMPX
        STY TEMPY
        LDX #$00                ;WAITS FOR SPECIFIED DURATION BETWEEN EACH NOTE
WOL:   INX
   LDY #$00
WIL:   INY
   CPY PAUSEY      ;WAIT MULTIPLIER
   BNE WIL
   CPX PAUSEX      ;WAIT DURATION
   BNE WOL
   LDY TEMPY
        LDX TEMPX
   INC
   RTS   



NOTEA:   LDA #$C6     ; sets timer 2 to the corresponding note frequency
   STA $A008    ;lsb
   LDA #$01
   STA $A009    ;msb
   JMP PLAY      


NOTEB:   LDA #$94
   STA $A008    ;lsb
   LDA #$01
   STA $A009    ;msb
   JMP PLAY   

NOTEC:   LDA #$7E
   STA $A008    ;lsb
   LDA #$01
   STA $A009    ;msb
   JMP PLAY

NOTED:   LDA #$54
   STA $A008    ;lsb
   LDA #$01
   STA $A009    ;msb
   JMP PLAY

NOTEE:   LDA #$2F
   STA $A008    ;lsb
   LDA #$01
   STA $A009    ;msb
   JMP PLAY

NOTEF:   LDA #$0E
   STA $A008    ;lsb
   LDA #$01
   STA $A009    ;msb
   JMP PLAY

NOTEG:   LDA #$FF
   STA $A008    ;lsb
   LDA #$00
   STA $A009    ;msb
   JMP PLAY


TUNE :  BYT #$01        ;NOTES FOR TUNE
        BYT #$02
   BYT #$03
   BYT #$04
   BYT #$05
   BYT #$06
   BYT #$07
   BYT #$08
   BYT #$07
   BYT #$06
   BYT #$05
   BYT #$04
   BYT #$03
   BYT #$02
   BYT #$01
   BYT #$02
   BYT #$04
   BYT #$06
   BYT #$08
   BYT #$07
   BYT #$05
   BYT #$03
   BYT #$01
        BYT #$FF      ;FF - end of tune




TMRSTP: LDA #$00           ; by setting shift reg to 000 it will
   STA $A00B        ; stop the timer and shift register

   ORG $FFFC
   WRD SETCB2

END         ; the end


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Dec 02, 2004 8:49 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8541
Location: Southern California
> i have come accross limited resources documenting this feature

You can find the data sheets on this website starting at http://www.6502.org/documents/datasheets/ See also my tips at http://www.6502.org/forum/viewtopic.php?t=342 There are four pages in that subject matter. What you're dealing with starts at about "Tip of the Day, #5".


> and all i have seen is that i should set bits 2-4 as 100 of ACR
>
> LDA #$08
> STA $A00B
>
> is this right?

No. You have it in bits 1-3. (Bit 0 is the 1's place.) You would want $10, not 8.

For clarity and having less confusion getting things working, I would recommend a couple of things here. In this case, the hex or even decimal value is irrelevant. To show individual bits, use LDA #00010000B. Also, use assembler labels wherever possible. A00B does not tell us humans much. You just have to remember what it is, or keep writing it in the comments. Near the top of the code there should be something like:
Code:
VIA:      EQU  A000
VIAPB:    EQU  VIA+0
VIAPA:    EQU  VIA+1
VIADDRB:  EQU  VIA+2
VIADDRA:  EQU  VIA+3
 ...
VIAACR:   EQU  VIA+B
 ...

Beside making it clear where you're storing the number, you have the added benefit of not having to find and change hundreds of lines of your program if a hardware change requires changing the base address of the VIA for example. You'd just change the one line and the assembler takes care of the rest.

Then your lines above will say
Code:
     LDA   #00010000B  ; Set VIA's SR to shift out
     STA   VIAACR      ; free-running under T2 control.


> Apparently, by changing the values in timer 2, the rate at which the
> shifting is done should change:
>
> LDA #$C6
> STA $A008
> LDA #$01
> STA A009

Unfortunately, T2CH will have no effect when using T2 for shift register timing. That means you're left with only 256 speeds, range from very, very high notes to ultrasonic. In fact, with a clock speed of about 10MHz or above, they'd all be ultrasonic. Not much good. Instead, use T1 free-running, toggling PB7. You'll get better resolution, and you can go down below 20Hz with a 2MHz clock speed. You say you wanted to use PB below. Can you use PA instead, so PB7 can be used for your square-wave output? Or do you have more than one VIA?

I should add here that there is something else related you can do with the shift register, which is to put an RC filter on CB2 and use it as a 9-level D/A converter. This is the equivalent of slightly more than 3 bits. Then you can play back a complex sampled waveform instead of just a square wave. Believe it or not, 9 levels is plenty for intelligible speech, DTMF, and other things. Some talking toys use only a 2-bit converter.


> Also do i need to set port B as an output or is this done automatically?

At reset, PA and PB are set to all inputs, not outputs. To make a bit an output, write a 1 to its corresponding bit in the data direction register. Making PB all outputs would require storing FF to VIADDRB.


> Any help really is GREATLY appreciated.

To simplify your code, why not have a note table instead of a routine for each note. Use the same routine to look up all the timer latch values from the table. That way it's easy to have the entire chromatic scale, as many octaves as you want.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Dec 03, 2004 6:19 pm 
Offline

Joined: Thu Dec 02, 2004 6:03 pm
Posts: 3
Thanks for your help.

I have had a look into using timer 1 and PB7. The datasheed has the essential info but its not too well documented elsewhere.

i have written this code....


Code:
ORG $F800
SETVAL:   SET TEMPY=$00
   SET TEMPX=$00
   SET PAUSEX=$50      ;PAUSEX/Y set to 50k cycles
   SET PAUSEY=$C3
   SET NOTENUM=$00      ;note number - next note to play - 00=start
   

SETCB2:   LDA #$FF
   STA $A002     ; set port B as output

TMRSET:   LDA#$50           ; set timer 1 to free run mode
   STA $A00B

NOTEA:   LDA #$C6     ;sets timer 1 to the corresponding note frequency
   STA $A004    ;lsb
   LDA #$01
   STA $A005    ;msb


WAIT:   STX TEMPX
        STY TEMPY
        LDX #$00                ;WAITS FOR SPECIFIED DURATION BETWEEN EACH NOTE
WOL:   INX
   LDY #$00
WIL:   INY
   CPY PAUSEY      ;WAIT MULTIPLIER
   BNE WIL
   CPX PAUSEX      ;WAIT DURATION
   BNE WOL
   LDY TEMPY
        LDX TEMPX
   INC

   JMP TMRSET   


END         ; the end



should that be ok ?

Also, if i had a short loop which kept setting the timer and the timer time, would that result in no wave being generated on PB7 ?

(if the code above is not correct, what should i be doing?)

thanks again.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Dec 04, 2004 1:30 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8541
Location: Southern California
> SETVAL: SET TEMPY=$00
> SET TEMPX=$00
> SET PAUSEX=$50 ;PAUSEX/Y set to 50k cycles
> SET PAUSEY=$C3
> SET NOTENUM=$00 ;note number - next note to play - 00=start

These appear to be zero page variables since you're storing to them later. If that's the case, you'll want to fix it so TEMPX and TEMPY are not the same location.


> TMRSET: LDA#$50 ; set timer 1 to free run mode
> STA $A00B

You want
Code:
      LDA  #11000000B  ; Set T1 for continuous timed inter-
      STA  VIA_ACR     ; rupts and sqare wave output on PB7

11000000B is $C0 but a hex number here wouldn't tell us anything useful because it's individual bits that matter here. If you had other things going that might be using the ACR and you didn't want to disturb those, you would OR-in bits 6 and 7 instead of blindly storing 0's to all the other bits.

Note that although the ACR is set to make T1 produce continuous timed interrupts, those interrupts will not be reflected at the VIA's IRQ output unless you also set the corresponding bit in the interrupt enable register (IER). IOW, it doesn't necessarily mean the processor will keep receiving interrupts.


> NOTEA: LDA #$C6 ;sets timer 1 to the corresponding note frequency
> STA $A004 ;lsb
> LDA #$01
> STA $A005 ;msb

How about using a single routine for the note:
Code:
NOTE: LDA  NOTE_TBL_LO,X
      STA  VIAT1CL
      LDA  NOTE_TBL_HI,X
      STA  VIAT1CH
      RTS
 ;----------------------

NOTE_TBL_LO:  DFB  <byte, byte, byte, byte, elc..>
NOTE_TLB_HI:  DFB  <byte, byte, byte, byte, etc..>

Then you'd put the note number in X and do JSR NOTE (or straight-line it if you wish).

If you want to assign even-number-only values to notes, or even put the note in the accumulator first and do a single ASL A (to multiply by two), you could but both the low byte and the high byte of the note together so you have a list of 16-bit words in the table, and then get it all in one table. That would make the table a little more programmer-friendly.

You could use a table for the delays as well, so you only have one delay routine whose delay is determined by the value you've stored in a variable. You can of course change the variable as often as you wish for different lengths of note, but it could remain unchanged for long periods if you have a series of notes that all have the same timing value (sixteenth notes for example.)

Turning the note off for a rest could be done in several ways, including disabling the free-running of the counter, disabling PB7 output, or even giving the counter a number that would result in a frequency too high to hear. If you disable the counter, remember to set the two high bits of the ACR again before writing to the counter. Oh, and one more thing (this is not in the data sheet)-- You can write to the T1 latches, but you'll have to write directly to the T1 counters to get it going after setting up the ACR.

I will strongly recommend that in order to make better programming progress in the long run, you work toward getting more of the numbers out of the code (for reasons stated in the last post), shortening the code by using look-up tables and factoring out subroutines, and if your assembler supports macros, learning to use them too. Modularizing becomes more and more important as program size grows. A macro is a piece of assembly-language programming that you yourself write, but then its internal details hide behind the name when you call it as if it were just a very sophisticated assembly-language instruction. Unlike subroutines, macros don't have the JSR/RTS penalty in runtime delays, and they can use conditional assembly to assemble the final code different ways depending on the parameters you give them. They usually have no penalty in program size or execution speed, and yet they effectively raise the level of the language. The point is to more clearly see the big picture, keep control of the project, make better progress, and produce fewer bugs. None of this means giving up any control of internal details-- it just means you don't have to be distracted by them when it's not time to be.


Last edited by GARTHWILSON on Mon Dec 06, 2004 7:50 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Dec 04, 2004 5:37 pm 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
http://www.6502.org/documents/datasheet ... r_2004.pdf

is really not complete for the description of the 6522! I think it is rather a starting point for experiments/tests!

thesylph005 asks if port B should be set to output mode in order to generate a continous square wave on the CB2 pin!

GARTHWILSON answers to this:

At reset, PA and PB are set to all inputs, not outputs. To make a bit an output, write a 1 to its corresponding bit in the data direction register. Making PB all outputs would require storing FF to VIADDRB.

Well this is true but not the answer to the question! This is how to set the the mode of the pins PA0-PA7 and PB0-PB7. But thesylph005 asks about the CB2 pin! For "handshake" data transfers CA1 and CB1 are control lines from the external device and CA2 and CB2 are control lines to the external device, i.e. CA1 and CB1 are in input mode and CA2 and CB2 in output mode. But CA2 and CB2 can also be in input mode. This is controlled by the bits 7 and 3 of PCR ($C). From the description of shift input in http://www.6502.org/documents/datasheet ... r_2004.pdf it is seen that CB1 is in output mode when "Shift In" is in operation. The only logical explanation would be that the modes of CB1 CB2 are controlled by bits 4,3,2 of of ACR ($B) and of bit7 of PCR ($C)as follows:

0 0 0 => CB1 input mode CB2 in the mode specified by bit7 of PCR ($C)
0 0 1 => CB1 output mode CB2 input mode
0 1 0 => CB1 output mode CB2 input mode
0 1 1 => CB1 output mode CB2 input mode
1 0 0 => CB1 output mode CB2 output mode
1 0 1 => CB1 output mode CB2 output mode
1 1 0 => CB1 output mode CB2 output mode
1 1 1 => CB1 output mode CB2 output mode

Is this true? I have not yet used the shift register functions! I always had bits 4,3,2 = 0 , CA1 and CB1 were control lines from the external device (input mode) and CA2 and CB2 were control lines to the external device (output mode).

If somebody (Garth?) knows exactly how the shift operations work why not describe it!

My guess:

When bits 4,3,2 of of ACR ($B) are 1 0 0 and data is written into the Shift Register ($A) the T2 Low-order latch is copied to the T2 low-order counter and the count down starts. When the T2 low-order counter reaches zero there is a shift (i.e. roll, SR7 is re-circulated back to SR0) ) and CB2 is set to the value of the bit(SR7 or SR0?). Then the T2 Low-order latch is again copied to the T2 low-order counter and the count down to next shift starts again etc.

Is this true? If yes, what happens if the T2 counter already was in use (by having written something to T2H ($09) ) ? And how is this "infinite loop" stopped? By writing to ACR ($B) setting the bits to something else then 1 0 0?


[/b]


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Dec 04, 2004 9:43 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8541
Location: Southern California
Quote:
http://www.6502.org/documents/datasheets/wdc/wdc_w65c22s_mar_2004.pdf

is really not complete for the description of the 6522! I think it is rather a starting point for experiments/tests!

Actually the data sheets are pretty complete-- not 100%, but close to it. Sometimes it seems like something's not there until you struggle over a problem for a long time, and when you finally get it figured out, you go back to the data sheet, and find the information was hiding there all along but there was no big red font calling your attention to the part that's easy to slip on. I've included a few things that aren't there, like that the proper sequence to get T1 running in free-run mode is to set up the ACR and then write directly to the counters, followed by writing to the latches later if you want to. That's something I got from an ap. note a Rockwell engineer faxed me years ago. The data sheets also won't tell you about the one bug with shifting under control of an external shift clock, but that's irrelevant when CB1 is outputting the shift clock.

I mostly use my Synertek data book for the VIA just because that's where I have all my notes, highlightings, etc.. Of course I keep in mind a few improvements in WDC's VIA, like that it has symmetrical totem-pole outputs and its inputs are high-impedance instead of presenting an LSTTL load. What the data sheets won't tell you is all the things you can do with the VIA. They just give you the sterile facts and it's up to the user to be creative in what can be done with the tools provided.


Quote:
thesylph005 asks if port B should be set to output mode in order to generate a continous square wave on the CB2 pin!

GARTHWILSON answers to this:

At reset, PA and PB are set to all inputs, not outputs. To make a bit an output, write a 1 to its corresponding bit in the data direction register. Making PB all outputs would require storing FF to VIADDRB.

Well this is true but not the answer to the question!

thesylph005 did not specifically link the PB output question with the CB1 & CB2 lines, so my assumption was that he wanted to use PB for something else in the project. I understand though that my answer could be confusing. The CA and CB pins are controlled by the ACR and PCR, not DDRA and DDRB. In my own many uses, I have always treated the ports' bit data direction as unrelated to the CA and CB pins. When they're used for the handshaking spoken of in the data sheet, it's mostly for things like feeding data to a parallel printer; but I've never used them that way even when I was feeding data to a printer with the VIA. There's more than one way to skin a cat. Anyway, the CB1 and CB2 data directions for shift register usage are set by the ACR bits that determine the shift register operation mode. One of our products flying in aircraft all over the world without problems uses the VIA's shift register without ever touching the PCR at all, anywhere in the program.

Although I have not specifically re-quoted all the earlier questions, this should provide answers. When questions seem to make wrong assumptions, it's sometimes more productive to change the approach.

Regarding CB1&2 data directions: When you're using the shift register (SR), the first of the three binary digits determining the SR mode tells the CB2 (data) direction. 0=input, 1=output, like bits in DDRA and DDRB. The next bit tells if T2 is used. 0=yes, 1=no. The last bit of the SR mode control is not quite as simple, but it will never be 0 when using an external shift clock source. I never really thought about it this way. I just look up the mode I want in the table in the data sheet.

Quote:
If somebody (Garth?) knows exactly how the shift operations work why not describe it!

I've used this IC a lot for scores of things. There's probably more that I'm forgetting to tell, but I'll be glad to keep answering questions as long as they come up. Sometimes the review is good for me anyway, and sometimes someone will ask something that drives me to try out something I'm not sure of.

In response to Mats' last two paragraphs: T2, when used separately from the shift register, is one-shot only. But when you use it with the SR, it does keep re-loading itself to start each new bit. Unless you're using SR mode 100, it will stop after the 8 bits are shifted in or out. If shifting out, the data on CB2 will retain the last bit's value until you give the SR another byte to shift out. T2 restarts itself for each byte. It is not necessary to keep writing to T2.

If you set up a SR mode that uses T2 even when T2 was already being used for something else first, it gets re-assigned to the SR. I have not tried this one, but the data sheet seems to be pretty clear on it, showing that T2 will count phase-2 cycles and not PB6 pulses for example. T2's high counter byte is ignored in SR use. (That information is hiding in the data sheet too.)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Dec 04, 2004 10:13 pm 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
Anyway this works:
Code:
;GENERATE SQUARE WAVE WITH FREQUENCY OSCILLATOR/(4*256)
T2CL   = $F8     ; T2 LOW ORDER LATCHES
SR     = $FA     ; SHIFT REGISTER
ACR    = $FB     ; AUXILARY CONTROL REGISTER
     *=$6000
     LDA #$10    ;SHIFT OUT FREE RUNNING AT T2 RATE
     STA ACR
     LDA #$FF
     STA T2CL    ;SET "T2 RATE" (LOWEST POSSIBLE $FF)
     LDA #$F0
     STA SR      ;BIT PATTERN 11110000 TO SHIFT REGISTER;
STO  BRA STO     ;READY!

I run it on my board.

But sometimes (very often) the W65C22S does not get properly initialised by power up and then nothing at all works!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Dec 04, 2004 10:41 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8541
Location: Southern California
> But sometimes (very often) the W65C22S does not get properly
> initialised by power up and then nothing at all works!

Having fast, clean edges on the reset pulse to the system (including to the VIAs) should take care of that; but actually I've never had any problem with a VIA failing to work because of a bad reset. All that the reset seems to do is to initialize the user-accessible registers, and you can set them up the way you want them by writing to them anyway. To do a software reset for the SR, you can write 000 to the three applicable bits in the ACR before proceeding.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Dec 05, 2004 9:15 am 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
Just some final remarks about the shifting:

The basic "Shift out - PHI2 Control (110)" is done with half the PHI2 rate, see Fig 1-11 of the Data Sheet. With "T2 Control" (101) this rate is further reduced with a factor N+2, see Fig 1-10 of the Data Sheet. With a 1 MHz oscillator the minimal shift clock rate with N=255 is therefore 1000/(2*(255+2)) MHz. This rate is then on CB1 as squarewave. By writing 11110000 to the shift register the frequency on CB2 is then again reduced with a factor 4 to 1000/(4*2*(255+2)) MHz= 486 Hz.

The reset problem with at least some of the newly produced W65C22S is another story! All I want to say at this time is that if strange faults occure it could be due to that a W65C22S malfunctions after a bad reset!


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Dec 05, 2004 12:00 pm 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
Finally a prototype program with the Garth recommended method with the output on PB7:
Code:
;GENERATE A SQUARE WAVE WITH FREQUENCY 1/8000 OF THE OSCILLATOR FREQUENCY ON PB7
; 8 MHZ => 1000 HZ  8000/2 = $0FA0
DDRB   = $F2     ; DATA DIRECTION REGISTER B
T1CL   = $F4     ; T1 LOW ORDER COUNTER
T1CH   = $F5     ; T1 HIGH ORDER COUNTER
ACR    = $FB     ; AUXILARY CONTROL REGISTER
     *=$6000
     LDA #$80
     STA DDRB    ;PB7 TO OUTPUT MODE
     LDA #$C0
     STA ACR     ;TIMER 1 IN FREE-RUN MODE, SQUARE WAVE OUTPUT
     LDA #$A0
     STA T1CL    ;LOW PART OF COUNT
     LDA #$0F
     STA T1CH    ;HIGH PART OF COUNT, THE COUNT-DOWN STARTS
STO  BRA STO     ;READY!


Works fine! Lowest frequency is oscillator frequency/(2*65535)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Dec 05, 2004 4:43 pm 
Offline

Joined: Sun Aug 24, 2003 7:17 pm
Posts: 111
And just a very last comment about the code of my last post!

In the Data Sheet it is explained that also in the Free-Run mode the Interrupt Flag Register bit is set when the T1 counter has reached zero. As in this case (tone generation) one certainly does not want an interrupt here one should assure that either corresponding Interrupt Enable Register bit is unset or the Interrupt Disable is set (SEI)

To make sure that the Interrupt Enable Register bit is unset:

Code:
  LDA #$40   ;01000000
  STA IER    ;Interrupt Enable Register


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Dec 05, 2004 8:17 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8541
Location: Southern California
When the device comes out of reset, all IER and IFR bits will be clear.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Dec 07, 2004 10:19 pm 
Offline

Joined: Thu Dec 02, 2004 6:03 pm
Posts: 3
hi guys. thanks for the help.

below if my full final code which seems to work.
i added 4 button sensors on A inputs 0-3 which choose a tune to play.

Code:


SETVAL:   SET TEMPX=$00
   SET TEMPY=$01
   SET PAUSEX=$02      
   SET PAUSEY=$03
   SET NOTENUM=$04
   SET TUNENUM=$05

   SET VIAT1L=$4004  ; via timer 1 locations
   SET VIAT1M=$4005   
   SET VIAACR=$400B  ; ACR address
   SET VIADDRB=$4002 ; DDRB address
   SET VIAIER=$400E  ; IER
   SET VIADDRA=$4003 ; A Data Direction Register
   SET VIADRA=$4001  ; A Data Register   
   
ORG $F800


        LDA #$00              ; initiate or reload values
        STA TEMPX
        STA TEMPY
        STA NOTENUM
        LDA #$50
        STA PAUSEX
        LDA #$C3
   STA PAUSEY


SETCB2:   LDA #$FF
   STA VIADDRB             ; set port B as output
   LDA #$00
   STA VIADDRA      ; set port A as inputs



MENU:   LDA #$00              ; initiate or reload values
        STA TEMPX
        STA TEMPY
        STA NOTENUM
       
        LDX VIADRA      ; LOAD x with VIA INPUT A
   STX TUNENUM      ; save input value to remember what button pressed

        CPX %00000001      ;check button 1
        BEQ PLAY      ;if on, play             
        CPX %00000010      ;check button 2
        BEQ PLAY      ;if on, play
        CPX %00000100      ;check button 3
        BEQ PLAY      ;if on, play
        CPX %00001000      ;check button 4
        BEQ PLAY      ;if on, play
        JMP MENU      ;LOOP
       


TMRSET:   LDA  %11000000          ; set timer 1 to repeat   ($c0)
   STA VIAACR      ; and interupt outputs on PB7

; ----------------NOT SURE IF THE 2 LINES BELOW ARE NEEDED-------------

INTSET: LDA #$40         ;01000000 Enable interupt for timer 1
    STA VIAIER          ;Interrupt Enable Register
; ---------------------------------------------------------------------






PLAY :   LDY NOTENUM      ; what note to play next
   INY         ; increment note number
   STY NOTENUM           ; store next note

   LDA TUNENUM      ; find out what tune we are playing

   CMP %00000001      ; run subroutine to load corresponding tune
   JSR LOAD1      ; x will be loaded with note Y from tunes table
   JSR TIMES1      ; LOAD THE WAIT TIME AS WELL

   CMP %00000010
   JSR LOAD2
   JSR TIMES2

   CMP %00000100
   JSR LOAD3
   JSR TIMES3

   CMP %00001000
   JSR LOAD4
   JSR TIMES4   
   
   
   CPX #$FF      ; FF symbolises end of tune
   BEQ ENDJUMP      ; then jump to end - TMRSTP via ENDJUMP
            ; otherwise

SETNOTE: LDA  NOTELSB,X    ; look up note X vlaues from notes tables and
         STA  VIAT1L       ; set the values into timer 1
         LDA  NOTEMSB,X
         STA  VIAT1M
         
   JSR WAIT      ; wait a while for the note to be played
   
   JMP PLAY      ; jump back up to play next note
   




ENDJUMP: JMP MENU      ; end of tune, go back to MENU





; --------------------- LOAD NOTE SUBROUTINES [accessed through PLAY method]----


LOAD1:   LDX TUNE1,Y      ; loads note number Y from TUNE1
   RTS

LOAD2:   LDX TUNE2,Y      ; loads note number Y from TUNE2
   RTS

LOAD3:   LDX TUNE3,Y      ; loads note number Y from TUNE3
   RTS

LOAD4:   LDX TUNE4,Y      ; loads note number Y from TUNE4
   RTS



TIMES1  LDA TIMES1,Y      ; GET WAIT TIME FROM TIMES TABLE
   STA PAUSEY
   RTS

TIMES2  LDA TIMES2,Y      ; GET WAIT TIME FROM TIMES TABLE
   STA PAUSEY
   RTS

TIMES3  LDA TIMES3,Y      ; GET WAIT TIME FROM TIMES TABLE
   STA PAUSEY
   RTS

TIMES4  LDA TIMES4,Y      ; GET WAIT TIME FROM TIMES TABLE
   STA PAUSEY
   RTS

;-------------------------------------------------------------------------------






WAIT:   STX TEMPX
        STY TEMPY
        LDX #$00                ;WAITS FOR SPECIFIED DURATION BETWEEN EACH NOTE
WOL:   INX
   LDY #$00
WIL:   INY
   CPY PAUSEY      ;WAIT MULTIPLIER
   BNE WIL
   CPX PAUSEX      ;WAIT DURATION
   BNE WOL
   LDY TEMPY
        LDX TEMPX
   INC
   RTS   






; --------------------- BELOW ARE TABLES FOR NOTES AND THE TUNES





TUNE1:  BYT #$01  ;   NOTES FOR TUNE ------
        BYT #$02
   BYT #$03
   BYT #$04
   BYT #$05
   BYT #$06
   BYT #$07
   BYT #$08
   BYT #$07
   BYT #$06
   BYT #$05
   BYT #$04
   BYT #$03
   BYT #$02
   BYT #$01
   BYT #$02
   BYT #$04
   BYT #$06
   BYT #$08
   BYT #$07
   BYT #$05
   BYT #$03
   BYT #$01
        BYT #$FF   ;FF - end of tune

TIMES1: BYT #$BF  ;   TIMING ------- [ 1/4 => 3F ][ 1/2 => 7F ][ 3/4 => BF ] [ 1/1 => FF ] 
        BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
        BYT #$BF   ; end of tune








TUNE2:  BYT #$01   ;   NOTES FOR TUNE
        BYT #$01
   BYT #$01
   BYT #$01
   BYT #$03
   BYT #$03
   BYT #$03
   BYT #$03
   BYT #$05
   BYT #$05
   BYT #$05
   BYT #$05
   BYT #$02
   BYT #$05
   BYT #$06
   BYT #$06
   BYT #$06
   BYT #$01
   BYT #$02
   BYT #$03
        BYT #$FF   ;FF - end of tune


TIMES2: BYT #$BF   ;     TIMING ------- [ 1/4 => 3F ][ 1/2 => 7F ][ 3/4 => BF ] [ 1/1 => FF ] 
        BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
        BYT #$FF   ;FF - end of tune









;--------------------------------- OCTAVES DEMO --------------------------------


TUNE3:  BYT #$00   ;C0   
        BYT #$04   ;E0
   BYT #$09   ;A0
   BYT #$0C   ;C1
   BYT #$10   ;E1
   BYT #$15   ;A1
   BYT #$18   ;C2
   BYT #$1C   ;E2
   BYT #$21   ;A2
   BYT #$24   ;C3
   BYT #$28   ;E3
   BYT #$2D   ;A3
   BYT #$30   ;C4
   BYT #$34   ;E4
   BYT #$39   ;A4
   BYT #$3C   ;C5
   BYT #$40   ;E5
   BYT #$45   ;A5
   BYT #$48   ;C6
   BYT #$4C   ;E6
   BYT #$51   ;A6
   BYT #$54   ;C7
   BYT #$59   ;E7
   BYT #$5D   ;A7
   BYT #$60   ;C8  TOP
   BYT #$64   ;PAUSE
   BYT #$30   ; LITTLE TUNEY THING BELOW
   BYT #$34
   BYT #$39
   BYT #$34
   BYT #$30
   BYT #$34
   BYT #$39
   BYT #$34   
   BYT #$39
   BYT #$3C
   BYT #$40
   BYT #$3C
   BYT #$39
   BYT #$3C
   BYT #$40
   BYT #$3C
   BYT #$30   
   BYT #$34
   BYT #$2D
   BYT #$24
   BYT #$24
   BYT #$24
   BYT #$24
   BYT #$48
        BYT #$FF   ;FF - end of tune



TIMES3: BYT #$BF   ;TIMING ------- [ 1/4 => 3F ][ 1/2 => 7F ][ 3/4 => BF ] [ 1/1 => FF ] 
   BYT #$BF   
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$7F
   BYT #$7F
   BYT #$7F
   BYT #$7F
   BYT #$7F
   BYT #$7F
   BYT #$7F
   BYT #$7F
   BYT #$7F
   BYT #$7F
   BYT #$7F
   BYT #$3F
   BYT #$3F
   BYT #$3F
   BYT #$3F
   BYT #$3F
   BYT #$3F
   BYT #$3F
   BYT #$3F
   BYT #$3F
   BYT #$3F
   BYT #$3F
   BYT #$3F
   BYT #$FF
   BYT #$FF
   BYT #$FF   ; END










;--------------------------------- HAPPY BIRTHDAY --------------------------------


TUNE4:  BYT #$37   ;G   
        BYT #$37   ;G
        BYT #$39   ;A
        BYT #$37   ;G
        BYT #$30   ;C
        BYT #$3B   ;B
        BYT #$64   ;NO NOTE REST
        BYT #$37   ;G
        BYT #$37   ;G
        BYT #$39   ;A
        BYT #$37   ;G
        BYT #$32   ;D
        BYT #$30   ;C
        BYT #$64   ;NO NOTE REST
        BYT #$37   ;G
        BYT #$37   ;G
        BYT #$42   ;G5
        BYT #$34   ;E
        BYT #$30   ;C
        BYT #$3B   ;B
        BYT #$39   ;A
        BYT #$64   ;NO NOTE REST
        BYT #$35   ;F
        BYT #$35   ;F
        BYT #$34   ;E
        BYT #$30   ;C
        BYT #$32   ;D
        BYT #$30   ;C
        BYT #$64   ;NO NOTE REST
   BYT #$FF   ; END

TIMES4: BYT #$BF   ;TIMING ------- [ 1/4 => 3F ][ 1/2 => 7F ][ 3/4 => BF ] [ 1/1 => FF ] 
   BYT #$BF   
   BYT #$BF
   BYT #$BF
   BYT #$FF
   BYT #$FF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$FF
   BYT #$FF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$FF
   BYT #$FF
   BYT #$BF
   BYT #$BF
   BYT #$FF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$FF
   BYT #$BF
   BYT #$BF
   BYT #$BF
   BYT #$FF   ; END





; -------------------NOTE TABLES---------------------------------



;------------------ TIMER 1 LSB VALUES-----------------------------

;------------------ROW NUMBER---NOTE-----

NOTELSB: BYT #$E4   ;00   C0
   BYT #$8D   ;01   C#0/Db0
   BYT #$49   ;02   D0
   BYT #$15   ;03   D#0/Eb0
   BYT #$F6   ;04   E0
   BYT #$E4   ;05   F0
   BYT #$E5   ;06   F#0/Gb0
   BYT #$F1   ;07   G0
   BYT #$0C   ;08   G#0/Ab0
   BYT #$34   ;09   A0
   BYT #$67   ;0A   A#0/Bb0
   BYT #$A7   ;0B   B0
   BYT #$F2   ;0C   C1
   BYT #$46   ;0D   C#1/Db1
   BYT #$A4   ;0E   D1
   BYT #$0B   ;0F   D#1/Eb1
   BYT #$7B   ;10   E1
   BYT #$F2   ;11   F1
   BYT #$72   ;12   F#1/Gb1
   BYT #$F8   ;13   G1
   BYT #$86   ;14   G#1/Ab1
   BYT #$1A   ;15   A1
   BYT #$B4   ;16   A#1/Bb1
   BYT #$53   ;17   B1
   BYT #$F8   ;18   C2
   BYT #$A3   ;19   C#2/Db2
   BYT #$52   ;1A   D2
   BYT #$05   ;1B   D#2/Eb2
   BYT #$BD   ;1C   E2
   BYT #$79   ;1D   F2
   BYT #$39   ;1E   F#2/Gb2
   BYT #$FC   ;1F   G2
   BYT #$C3   ;20   G#2/Ab2
   BYT #$8D   ;21   A2
   BYT #$5A   ;22   A#2/Bb2
   BYT #$29   ;23   B2
   BYT #$FC   ;24   C3
   BYT #$D1   ;25   C#3/Db3
   BYT #$A9   ;26   D3
   BYT #$82   ;27   D#3/Eb3
   BYT #$5E   ;28   E3
   BYT #$3C   ;29   F3
   BYT #$1C   ;2A   F#3/Gb3
   BYT #$FE   ;2B   G3
   BYT #$E1   ;2C   G#3/Ab3
   BYT #$C6   ;2D   A3
   BYT #$AD   ;2E   A#3/Bb3
   BYT #$94   ;2F   B3
   BYT #$7E   ;30   C4
   BYT #$68   ;31   C#4/Db4
   BYT #$54   ;32   D4
   BYT #$41   ;33   D#4/Eb4
   BYT #$2F   ;34   E4
   BYT #$1E   ;35   F4
   BYT #$0E   ;36   F#4/Gb4
   BYT #$FF   ;37   G4
   BYT #$F0   ;38   G#4/Ab4
   BYT #$E3   ;39   A4
   BYT #$D6   ;3A   A#4/Bb4
   BYT #$CA   ;3B   B4
   BYT #$BF   ;3C   C5
   BYT #$B4   ;3D   C#5/Db5
   BYT #$AA   ;3E   D5
   BYT #$A0   ;3F   D#5/Eb5
   BYT #$97   ;40   E5
   BYT #$8F   ;41   F5
   BYT #$87   ;42   F#5/Gb5
   BYT #$7F   ;43   G5
   BYT #$78   ;44   G#5/Ab5
   BYT #$71   ;45   A5
   BYT #$6B   ;46   A#5/Bb5
   BYT #$65   ;47   B5
   BYT #$5F   ;48   C6
   BYT #$5A   ;49   C#6/Db6
   BYT #$55   ;4A   D6
   BYT #$50   ;4B   D#6/Eb6
   BYT #$4B   ;4C   E6
   BYT #$47   ;4D   F6
   BYT #$43   ;4E   F#6/Gb6
   BYT #$3F   ;4F   G6
   BYT #$3C   ;50   G#6/Ab6
   BYT #$38   ;51   A6
   BYT #$35   ;52   A#6/Bb6
   BYT #$32   ;53   B6
   BYT #$2F   ;54   C7
   BYT #$2D   ;55   C#7/Db7
   BYT #$2A   ;56   D7
   BYT #$28   ;57   D#7/Eb7
   BYT #$25   ;58   E7
   BYT #$23   ;59   F7
   BYT #$21   ;5A   F#7/Gb7
   BYT #$1F   ;5B   G7
   BYT #$1E   ;5C   G#7/Ab7
   BYT #$1C   ;5D   A7
   BYT #$1A   ;5E   A#7/Bb7
   BYT #$19   ;5F   B7
   BYT #$17   ;60   C8
   BYT #$16   ;61   C#8/Db8
   BYT #$15   ;62   D8
   BYT #$14   ;63   D#8/Eb8
   BYT #$FF   ;64   NO NOTE


;----------------------TIMER 1 MSB VALUES-----------------------


;------------------ROW NUMBER---NOTE-----

NOTEMSB: BYT #$17   ;00   C0
   BYT #$16   ;01   C#0/Db0
   BYT #$15   ;02   D0
   BYT #$14   ;03   D#0/Eb0
   BYT #$12   ;04   E0
   BYT #$11   ;05   F0
   BYT #$10   ;06   F#0/Gb0
   BYT #$0F   ;07   G0
   BYT #$0F   ;08   G#0/Ab0
   BYT #$0E   ;09   A0
   BYT #$0D   ;0A   A#0/Bb0
   BYT #$0C   ;0B   B0
   BYT #$0B   ;0C   C1
   BYT #$0B   ;0D   C#1/Db1
   BYT #$0A   ;0E   D1
   BYT #$0A   ;0F   D#1/Eb1
   BYT #$09   ;10   E1
   BYT #$08   ;11   F1
   BYT #$08   ;12   F#1/Gb1
   BYT #$07   ;13   G1
   BYT #$07   ;14   G#1/Ab1
   BYT #$07   ;15   A1
   BYT #$06   ;16   A#1/Bb1
   BYT #$06   ;17   B1
   BYT #$05   ;18   C2
   BYT #$05   ;19   C#2/Db2
   BYT #$05   ;1A   D2
   BYT #$05   ;1B   D#2/Eb2
   BYT #$04   ;1C   E2
   BYT #$04   ;1D   F2
   BYT #$04   ;1E   F#2/Gb2
   BYT #$03   ;1F   G2
   BYT #$03   ;20   G#2/Ab2
   BYT #$03   ;21   A2
   BYT #$03   ;22   A#2/Bb2
   BYT #$03   ;23   B2
   BYT #$02   ;24   C3
   BYT #$02   ;25   C#3/Db3
   BYT #$02   ;26   D3
   BYT #$02   ;27   D#3/Eb3
   BYT #$02   ;28   E3
   BYT #$02   ;29   F3
   BYT #$02   ;2A   F#3/Gb3
   BYT #$01   ;2B   G3
   BYT #$01   ;2C   G#3/Ab3
   BYT #$01   ;2D   A3
   BYT #$01   ;2E   A#3/Bb3
   BYT #$01   ;2F   B3
   BYT #$01   ;30   C4
   BYT #$01   ;31   C#4/Db4
   BYT #$01   ;32   D4
   BYT #$01   ;33   D#4/Eb4
   BYT #$01   ;34   E4
   BYT #$01   ;35   F4
   BYT #$01   ;36   F#4/Gb4
   BYT #$00   ;37   G4
   BYT #$00   ;38   G#4/Ab4
   BYT #$00   ;39   A4
   BYT #$00   ;3A   A#4/Bb4
   BYT #$00   ;3B   B4
   BYT #$00   ;3C   C5
   BYT #$00   ;3D   C#5/Db5
   BYT #$00   ;3E   D5
   BYT #$00   ;3F   D#5/Eb5
   BYT #$00   ;40   E5
   BYT #$00   ;41   F5
   BYT #$00   ;42   F#5/Gb5
   BYT #$00   ;43   G5
   BYT #$00   ;44   G#5/Ab5
   BYT #$00   ;45   A5
   BYT #$00   ;46   A#5/Bb5
   BYT #$00   ;47   B5
   BYT #$00   ;48   C6
   BYT #$00   ;49   C#6/Db6
   BYT #$00   ;4A   D6
   BYT #$00   ;4B   D#6/Eb6
   BYT #$00   ;4C   E6
   BYT #$00   ;4D   F6
   BYT #$00   ;4E   F#6/Gb6
   BYT #$00   ;4F   G6
   BYT #$00   ;50   G#6/Ab6
   BYT #$00   ;51   A6
   BYT #$00   ;52   A#6/Bb6
   BYT #$00   ;53   B6
   BYT #$00   ;54   C7
   BYT #$00   ;55   C#7/Db7
   BYT #$00   ;56   D7
   BYT #$00   ;57   D#7/Eb7
   BYT #$00   ;58   E7
   BYT #$00   ;59   F7
   BYT #$00   ;5A   F#7/Gb7
   BYT #$00   ;5B   G7
   BYT #$00   ;5C   G#7/Ab7
   BYT #$00   ;5D   A7
   BYT #$00   ;5E   A#7/Bb7
   BYT #$00   ;5F   B7
   BYT #$00   ;60   C8
   BYT #$00   ;61   C#8/Db8
   BYT #$00   ;62   D8
   BYT #$00   ;63   D#8/Eb8
   BYT #$FF   ;64   NO NOTE

   


;--------------------------------------END OF NOTES TABLES---------




TMRSTP: LDA #$00        ; by setting shift reg to 000 it will
   STA VIAACR        ; stop the timer
   RTS

   ORG $FFFC
   WRD SETCB2

END         ; the end





this latest version has not been fully tested. but the main parts of the code seem to be ok.

thanks again for the help


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


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: