SB BBC @ GBR Oldie hints/tips #075-079 Hints and tips from the archives of Wakefield BBC Micro User Group... 75. Random numbers not including zero ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ There are times when you may want to generate a random number, which can be positive or negative, but which must not include zero. Alternatively, you may wish to multiply something by -1 or +1 at random, perhaps to determine which way a monster will turn in a maze etc.. An easy way to generate -1 or +1 is with Z=SGN(RND) , (the brackets are optional). RND on its own generates a number between -2147483648 and +2147483647, so its SGN can only be -1, 0 or +1. Since the likelihood of RND generating zero is about one in 4000 million, the result for all practical purposes is always -1 or +1! To generate a random number between say, -9 and +9 , but not including zero, you could use Z=RND(9)*SGN(RND). Thanks to James Slater for passing this idea on. 76. Jumping out of loops, procedures etc. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ As you know, it is very risky to use GOTOs to jump out of FOR-NEXT and REPEAT-UNTIL loops, or out of Functions and Procedures. Sooner or later you will get an error message along the lines of "Too many FORs", or else various odd things will start to happen. However, if your program has error-trapping with ON ERROR GOTO, you may have noticed that it doesn't seem to matter how many times you jump out of whatever the program is doing, to go back to the main menu, nothing untoward happens. Thus, if you could generate an Escape from within the program, you could happily jump out of anything, provided that you didn't jump into the middle of something else. This is possible in various "dirty" ways, such as CALL &9848 (Basic-1), CALL &9838 (Basic-2), and CALL &F9AB (OS 1.20). These are very naughty, as they vary with Basic or Operating System versions, and are not Tube compatible. The tidy way is with *FX153,0,27 and this works very well. *FX153 is very similar to *FX138, which some of you may know, but it accepts the Escape character as an error, and not just as an ASCII code like any other key. When jumping out of Procedures or Functions, the micro will not release LOCAL variables, so they may clash if used in the main body of the program, (ie. with Global variables). This call will not work if you have disabled the Escape key with *FX200 or *FX229, so if you really must do it like that, then CALL &F9AB is the best of the dirty methods. 77. *FX lookalike ~~~~~~~~~~~~~ You cannot use variables or Hex numbers in *FX calls, and they must go at the end of a line. This Procedure performs a *FX call; you can use variables or Hex numbers, and it can go anywhere on a line. Call it with PROCfx(a,x,y) where a,x & y are the three normal parameters, (use zeroes if there are less than three). Eg, *FX5,1 would be equivalent to PROCfx(5,1,0) . Note that A%,X% & Y% are implied LOCAL variables, so will not clash if used elsewhere in the program. 1000 DEFPROCfx(A%,X%,Y%):CALL&FFF4:ENDPROC 78. Reading *FX calls ~~~~~~~~~~~~~~~~~ *FX, (Osbyte), calls 156 and 165 upwards, are special read/write ones. (See the Advanced User Guide for full details.) You may write to them from BASIC with *FXa,x where a is the call number, and x is the new value to be written, eg *FX229,3 . You can also read the existing value, without altering it, using FNfx(a). Eg value=FNfx(229) . Note that strictly speaking, you should add X%=0 to line 2000, but defining LOCAL variables automatically sets them to zero, so you need not bother. 2000 DEFFNfx(A%):LOCALX%,Y%:Y%=&FF 2010 =(USR(&FFF4)AND&FF00)DIV&100 79. User port experimenting (3) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Here is a little program to enable you to use your micro as an AF signal generator. The tone is emitted as a 5 Volt p-p squarewave on pin PB7 of the User Port. I suggest you connect a 0.1uF capacitor and a 10k resistor in series with the output, to protect the 6522 VIA chip. The program initially generates 1000 Hz, and you then enter the frequency required. The timing increments available are fairly coarse, especially near the 25kHz end, so the frequency you actually get will not be exactly what you asked for. The maximum frequency possible is 250kHz, but the next increment down is 167kHz, which isn't very helpful! You can hear the tone by connecting a CRYSTAL earphone or microphone insert across the output, or by feeding it into an amplifier. 10 ON ERROR GOTO 80 20 ?&FE6B=&C0:?&FE64=&F2:?&FE65=1:freq%=1000 30 REPEAT:F%=10^6/freq%/2-1.5:?&FE66=F% MOD 256:?&FE67=F% DIV 256 40 actual%=10^6/((F%+2)*2)+0.5 50 PRINT"Generating: ";actual%" Hz"' 60 REPEAT:INPUT"Frequency ? "freq%:UNTIL freq%>49 AND freq%<25001 70 UNTIL FALSE 80 REPORT:PRINT" at line ";ERL:?&FE6B=0 73 Rick G4BLT @ GB7WRG