;
;   Pseudorandom digital white noise generator for PIC series.
;
;   PIC12C508 version written April 7th, 1997 by Scott Rider.
; Questions/comment to chip@aeug.org
;
;   This program uses Microchip assembler mnemonics and the Microchip
; MPASM assembler (http://www.microchip.com/).  Default config options
; are set in the __FUSES line below: MCLRE off, CP off, WDT off, OSC=INTRC.
;
;                  _______  _______
;                 |       \/       |
;     (+5V) Vdd --+ 1            8 +-- Vss (GND)
;                 |                |                      470
;   X1/CLKI/GP5 --+ 2            7 +-- GP0 (audio out) --/\/\/-- (spkr)
;    (not used)   |                |                  |   10K   1uF
;   X2/CLKO/GP4 --+ 3            6 +-- GP1             --/\/\/--|(-- (line)
;    (not used)   |                |  (not used)
;     GP3/!MCLR --+ 4            5 +-- GP2
;    (not used)   |  (PIC12C508)   |  (not used)
;                 +----------------+
;
;   This program generates a continuous stream of white noise through a
; speaker connected (via a 470-ohm series resistor) to pin GP0 of a
; PIC12C508.  It demonstrates an easy method for generating a seemingly
; random stream of bits. Hardware folks will probably recognize it as the
; tapped shift register technique covered in the CMOS Cookbook by Don
; Lancaster.
;
; Adapted from the original PIC16C54 (Parallax) version by Scott Edwards.
;
	list    p=12c508
	radix   dec
	include "p12c508.inc"

	__FUSES _MCLRE_OFF &_CP_OFF & _WDT_OFF & 0xFFE  ;Internal osc.

	cblock  0x07    ;Variables
		i       ;Loop counter
		x       ;Scratch
		y       ;Scratch
		sr0     ;32 bits of shift register
		sr1
		sr2
		sr3     ;/
	endc

	org      0x0            
;
;  PIC12C508 cold starts at 0XFFF (where it loads a factory-programmed
; internal osc. calibrate value).  It then rolls over to 0x0.
;
	movwf   OSCCAL
	goto    start
;
;  Subroutines in 12-bit PIC series must go on bottom page of ROM.
;
wait    movlw   35      ;Change this number for different sound if using
	movwf   i       ;'wait' rotuine (normally disabled).
loop    decfsz  i,F
	goto    loop
	retlw   0
;
;  Main code area traditionally starts at 0x100 on a 12-bit PIC.
;
	org     0x100

start   movlw   b'11000000'     ;Turn off T0CKI
	option                  ;/
	movlw   b'00000000'     ;Preset outputs to come up low
	movwf   GPIO            ;/
	movlw   b'00000000'     ;Set the I/O direction (all bits output)
	tris    GPIO

	clrf    sr0             ;Might as well start with a seed of 1.6E7.
	clrf    sr1
	clrf    sr2
	clrf    sr3
	incf    sr3,F           ;/
;
;   The main loop 'taps' is 24 CPU cycles.  At the 4MHz internal clock
; rate, the noise output is operating at a max. rate of about 21KHz.
;
taps    btfss   sr3,6           ;Get bits 18 and 31 for the feedback XOR.
	bcf     x,0
	btfsc   sr3,6
	bsf     x,0             ;Bit 31 -> x

	btfss   sr2,1
	bcf     y,0
	btfsc   sr2,1
	bsf     y,0             ;Bit 18 -> y

	movf    y,W             ;!(x XOR y) -> carry
	xorwf   x,F

	btfsc   x,0
	bcf     STATUS,C
	btfss   x,0
	bsf     STATUS,C        ;/

	rlf      sr0,F          ;32-bit shift
	rlf      sr1,F
	rlf      sr2,F
	rlf      sr3,F          ;/
;
;  Put a pseudorandom bit out to the speaker.  In this example, GPIO bit 0
; (pin 7 on the PIC12C508) is used.  Be sure to use a 470 ohm resistor for
; speaker or 10K or better for input to an op-amp/divider/whatever.
;
;  Also, to use all six GP bits for noise, just comment the following 4
; lines and uncomment the 5th and 6th lines.
;
	btfss   sr3,7           ;line 1
	bcf     GPIO,0          ;line 2
	btfsc   sr3,7           ;line 3
	bsf     GPIO,0          ;line 4

;       movf    sr3,W           ;line 5
;       movwf   GPIO            ;line 6

;
;  Uncomment the following 'call wait' to experiment with changing the
; 'texture' of the noise (see 'wait' routine, above).
;
;       call     wait           ;Optional delay routine to alter sound

	goto     taps           ;Ad infinitum...
;
;  That's all, folks!
;
	end
