//;***************************************************************************** //; HZTest * //; Automatic rotor control firmware * //; Dr. Pedro E. Colla (LU7HZ) * //; 2012 Free for amateur uses * //;***************************************************************************** //; PIC configuration bits * //;***************************************************************************** //_CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT //;***************************************************************************** program HZTest; { Declarations section } //;***************************************************************************** //#define bit_K h'DA' ; hex DA = 1200 bits/sec (218) * // ; hex 6b = 2400 bits/sec (107) * // ; hex 32 = 4800 bits/sec (50) * // ; hex 17 = 9600 bits/sec (23) * // ; hex 0A =19200 bits/sec (10) * //****************************************************************************** Const bit_K : byte = 50; //value calculated with program PicLoops half_bit : byte = bit_K / 4; //Half loop (experimental 1/4 loop) cw = 0 ; register; ccw = 1 ; register; rotor = 2 ; register; rxpin = 3 ; register; setauto = 4 ; register; txpin = 5 ; register; moving = 7 ; register; bounce = 5 ; register; adcon = 4 ; register; busy = 3 ; register; done = 1 ; register; Label Init,bit_delay; Var delay_cntr : Byte; long_cntr : Byte; cnt : Byte; rxchar : Byte; txchar : Byte; ct : Byte; p : Byte; {******************************************************************************} {* Rotor Control Word (RCW) *} {* (7) Rotor movement enabled (moving) *} {* (6) not used *} {* (5) GP4 debounce logic (bounce) *} {* (4) ADC Conversion state (adcon) *} {* (3) busy flag *} {* (2) not used *} {* (1) not used *} {* (0) not used *} {******************************************************************************} RCW : Byte; //*----------------------------------------------------------------------------* //* Boot process to initialize processor registers and program variables * //*----------------------------------------------------------------------------* Procedure BootFirmware; begin Asm bcf STATUS,RP0 ;bank 9 clrf GPIO ;clear outputs clrf INTCON ;clear interrupts movlw $07 ;turn comparator off movwf CMCON ; movlw $09 ;turn adc on and set word to left movwf ADCON0 ; ; bsf STATUS,RP0 ; bank 1 {$IFNDEF OSCAL} call $03FF ; get factory calibration value movwf OSCCAL ; set OSCCAL calibration value {$ENDIF} ;*---------[I/O Mapping]--------------------* ;| GP5 (out) (dig) pin 2 serial out | ;| GP4 (in) (dig) pin 3 set / start auto | ;| GP3 (in) (dig) pin 4 serial in | ;| GP2 (in) (an0) pin 5 rotor/reference V | ;| GP1 (out) (dig) pin 6 turn CCW rotor | ;| GP0 (out) (dig) pin 7 turn CW rotor | ;*------------------------------------------* movlw %00011100 ; TRISIO set movwf TRISIO ; all others inputs ; clrf ANSEL ; set all pins to digital mode movlw %00000100 ; ANSEL set AN2 pin 5 as analog movwf ANSEL ; clrf PIE1 ;Clear interrupts and misc registers clrf IOC ; clrf WPU ; clrf VRCON ; movlw %00001111 ;Set option_reg register movwf OPTION_REG ; ; bcf STATUS,RP0 ; switch back to bank 0 clrf GPIO ; clrf ADRESH clrf _RCW bsf GPIO,5 end; end; //*----------------------------------------------------------------------------* //* delay of one bit at the target speed * //* Routine and delay calculated with PicLoops.exe * //*----------------------------------------------------------------------------* Procedure bit_delay; begin { } Asm { } movlw _bit_K { } movwf _delay_cntr { } { } loop: { } nop {cLoops code excerpt } decfsz _delay_cntr,1 { } goto loop { } { } end; { } { } end; //*----------------------------------------------------------------------------* //* delay of one bit at the target speed (porque hay dos??) * //*----------------------------------------------------------------------------* procedure long_delay; begin asm movlw 100 movwf _long_cntr loop_R: call _bit_delay decfsz _long_cntr,1 goto loop_R end; end; //*----------------------------------------------------------------------------* //* delay of half bit at the target speed * //* Routine and delay calculated with PicLoops.exe * //*----------------------------------------------------------------------------* procedure start_delay; begin Asm { } movlw _half_bit movwf _delay_cntr { } loop_R2: { } nop {icLoops code excerpt } decfsz _delay_cntr,1 { } goto loop_R2 { } end; { } end; { } //*----------------------------------------------------------------------------* //* Transmit a single character over serial (blocking) * //*----------------------------------------------------------------------------* Procedure send232(Var c : byte); { } { } begin { } //; RS-232C serial out. the byte in file register //; xmt_bute will transmit cnt := $08; {*-----------------------------*} txchar := c; GPIO.txpin := 0; {Set 8 bits to send, lower GP5 } bit_delay; {and wait for one bit length } {*-----------------------------*} {*-----------------------------*} Asm txloop: rrf _txchar,1 btfss STATUS,C ;btfsc STATUS,0 for direct connection ;btfss STATUS,0 for standard connection bcf GPIO,5 btfsc STATUS,C ;btfss STATUS,0 for direct connection ;btfsc STATUS,0 for standard connection bsf GPIO,5 call _bit_delay decfsz _cnt,1 goto txloop bsf GPIO,5 ;bcf for direct connection ;bsf for standard connection call _bit_delay end; end; //*----------------------------------------------------------------------------* //* Receive a single character (blocking while receiving) * //*----------------------------------------------------------------------------* Function get232(Var error : byte ) : byte; { } { } begin { } //*---------------------------------------------{-------------------------------} cnt := $08; rxchar := $00; if GPIO.3 <> 0 then begin error := $ff; result:= $00; exit; end; start_delay; if GPIO.3 <> 0 then begin error := $ff; result:= $00; exit; end; Asm //----------------------------------------------{-------------------------------} receive: call _bit_delay btfss GPIO,3 ;btfsc if connect via 22k resistor ;btfss if standard connection bcf STATUS,C btfsc GPIO,3 ;btfss if connect via 22k resistor ;btfsc if standard connection bsf STATUS,C rrf _rxchar,1 decfsz _cnt,1 goto receive endrx: end; result := rxchar; error := $00; end; //*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=** //* Main Program Loop * //*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=** begin //*--------------------------------------------{-------------------------------*} {* Boot the firmware to start *} {*------------------------------*} BootFirmware; //*--------------------------------------------{-------------------------------*} {* Master Diagnostics Mode *} {* Enter mode if GP4 is pressed *} {* during initialization time *} {*------------------------------*} ct := ';'; Send232(ct); {Conditional compilation } while GPIO.setauto = 0 do begin {Debounce before start } end; { } while true do begin {Infinite loop need to reboot } {to exit back into normal mode } ct := get232(p); {Receive a character } if p = 0 then begin {If no error (there is a char } send232(ct); {Transmit it } end; { } if ADCON0.1 = 0 then begin {Take a sample from GP2 (analog) } if ADRESH > 128 then begin {If result is >128 turn GP0 on } GPIO.ccw := 1; { } end else begin { } GPIO.ccw := 0; {otherwise off } end; { } ADCON0.1 := 1; {and resample again } end; { } GPIO.cw := not(GPIO.setauto); {GP0 is complement of GP4 } if GPIO.setauto = 0 then begin {If GP4 is pressed during exec } while GPIO.setauto = 0 do begin {While pressed } ct := 'U'; {Keep sending 'U' which forms } send232(ct); {a square wave at the serial port} end; {for testing and callibration } end; {purposes, half period should } end; {be around 2 mSecs for 4800 bps } end.