| 
									
										
										
										
											2020-10-25 13:58:18 -04:00
										 |  |  | module q65_decode
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-25 13:58:18 -04:00
										 |  |  |    type :: q65_decoder
 | 
					
						
							|  |  |  |       procedure(q65_decode_callback), pointer :: callback
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  |    contains
 | 
					
						
							|  |  |  |       procedure :: decode
 | 
					
						
							| 
									
										
										
										
											2020-10-25 13:58:18 -04:00
										 |  |  |    end type q65_decoder
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |    abstract interface
 | 
					
						
							| 
									
										
										
										
											2020-10-25 13:58:18 -04:00
										 |  |  |       subroutine q65_decode_callback (this,nutc,sync,nsnr,dt,freq,    &
 | 
					
						
							| 
									
										
										
										
											2020-11-30 13:14:18 -05:00
										 |  |  |          decoded,nap,ntrperiod)
 | 
					
						
							| 
									
										
										
										
											2020-10-25 13:58:18 -04:00
										 |  |  |          import q65_decoder
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  |          implicit none
 | 
					
						
							| 
									
										
										
										
											2020-10-25 13:58:18 -04:00
										 |  |  |          class(q65_decoder), intent(inout) :: this
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  |          integer, intent(in) :: nutc
 | 
					
						
							|  |  |  |          real, intent(in) :: sync
 | 
					
						
							|  |  |  |          integer, intent(in) :: nsnr
 | 
					
						
							|  |  |  |          real, intent(in) :: dt
 | 
					
						
							|  |  |  |          real, intent(in) :: freq
 | 
					
						
							|  |  |  |          character(len=37), intent(in) :: decoded
 | 
					
						
							|  |  |  |          integer, intent(in) :: nap
 | 
					
						
							|  |  |  |          integer, intent(in) :: ntrperiod
 | 
					
						
							| 
									
										
										
										
											2020-10-25 13:58:18 -04:00
										 |  |  |       end subroutine q65_decode_callback
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  |    end interface
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | contains
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-24 09:51:02 -05:00
										 |  |  |   subroutine decode(this,callback,iwave,nutc,ntrperiod,nsubmode,nfqso,      &
 | 
					
						
							|  |  |  |        ntol,ndepth,lclearave,emedelay,mycall,hiscall,hisgrid,nQSOprogress,  &
 | 
					
						
							|  |  |  |        ncontest,lapcqonly)
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-25 13:58:18 -04:00
										 |  |  | ! Decodes Q65 signals
 | 
					
						
							| 
									
										
										
										
											2020-10-09 13:16:25 -04:00
										 |  |  | ! Input:  iwave            Raw data, i*2
 | 
					
						
							|  |  |  | !         nutc             UTC for time-tagging the decode
 | 
					
						
							|  |  |  | !         ntrperiod        T/R sequence length (s)
 | 
					
						
							|  |  |  | !         nsubmode         Tone-spacing indicator, 0-4 for A-E
 | 
					
						
							|  |  |  | !         nfqso            Target signal frequency (Hz)
 | 
					
						
							|  |  |  | !         ntol             Search range around nfqso (Hz)
 | 
					
						
							| 
									
										
										
										
											2020-11-11 11:14:02 -05:00
										 |  |  | !         ndepth           Optional decoding level
 | 
					
						
							| 
									
										
										
										
											2020-10-09 13:16:25 -04:00
										 |  |  | ! Output: sent to the callback routine for display to user
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  |     use timer_module, only: timer
 | 
					
						
							| 
									
										
										
										
											2020-10-27 13:08:07 -04:00
										 |  |  |     use packjt77
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  |     use, intrinsic :: iso_c_binding
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  |     use q65                               !Shared variables
 | 
					
						
							| 
									
										
										
										
											2020-12-27 15:27:26 -05:00
										 |  |  |  
 | 
					
						
							| 
									
										
										
										
											2020-10-09 13:16:25 -04:00
										 |  |  |     parameter (NMAX=300*12000)            !Max TRperiod is 300 s
 | 
					
						
							| 
									
										
										
										
											2020-10-25 13:58:18 -04:00
										 |  |  |     class(q65_decoder), intent(inout) :: this
 | 
					
						
							|  |  |  |     procedure(q65_decode_callback) :: callback
 | 
					
						
							| 
									
										
										
										
											2020-10-09 13:16:25 -04:00
										 |  |  |     character(len=12) :: mycall, hiscall  !Used for AP decoding
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  |     character(len=6) :: hisgrid
 | 
					
						
							| 
									
										
										
										
											2020-10-09 13:16:25 -04:00
										 |  |  |     character*37 decoded                  !Decoded message
 | 
					
						
							| 
									
										
										
										
											2020-10-27 13:08:07 -04:00
										 |  |  |     character*77 c77
 | 
					
						
							| 
									
										
										
										
											2020-10-30 11:07:44 -04:00
										 |  |  |     character*78 c78
 | 
					
						
							| 
									
										
										
										
											2020-08-08 09:14:12 -04:00
										 |  |  |     integer*2 iwave(NMAX)                 !Raw data
 | 
					
						
							| 
									
										
										
										
											2020-10-17 13:16:46 -04:00
										 |  |  |     real, allocatable :: dd(:)            !Raw data
 | 
					
						
							| 
									
										
										
										
											2020-10-27 13:22:02 -04:00
										 |  |  |     integer dat4(13)                      !Decoded message as 12 6-bit integers
 | 
					
						
							| 
									
										
										
										
											2020-10-30 11:07:44 -04:00
										 |  |  |     integer apmask1(78),apsymbols1(78)
 | 
					
						
							| 
									
										
										
										
											2020-11-22 13:58:29 -05:00
										 |  |  |     integer dgen(13)
 | 
					
						
							| 
									
										
										
										
											2020-12-15 11:03:06 -05:00
										 |  |  |     integer codewords(63,206)
 | 
					
						
							| 
									
										
										
										
											2020-12-24 09:51:02 -05:00
										 |  |  |     logical lclearave,lapcqonly,unpk77_success
 | 
					
						
							| 
									
										
										
										
											2020-10-09 13:16:25 -04:00
										 |  |  |     complex, allocatable :: c00(:)        !Analytic signal, 6000 Sa/s
 | 
					
						
							|  |  |  |     complex, allocatable :: c0(:)         !Analytic signal, 6000 Sa/s
 | 
					
						
							| 
									
										
										
										
											2020-08-01 12:13:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-30 16:12:02 -05:00
										 |  |  |     idec=-1
 | 
					
						
							| 
									
										
										
										
											2020-09-25 12:21:57 -04:00
										 |  |  |     mode65=2**nsubmode
 | 
					
						
							| 
									
										
										
										
											2020-11-15 12:21:08 -05:00
										 |  |  |     npts=ntrperiod*12000
 | 
					
						
							| 
									
										
										
										
											2020-08-08 09:14:12 -04:00
										 |  |  |     nfft1=ntrperiod*12000
 | 
					
						
							|  |  |  |     nfft2=ntrperiod*6000
 | 
					
						
							| 
									
										
										
										
											2020-12-30 16:12:02 -05:00
										 |  |  |     if(lclearave) nsave=0
 | 
					
						
							| 
									
										
										
										
											2020-11-15 12:21:08 -05:00
										 |  |  |     allocate(dd(npts))
 | 
					
						
							| 
									
										
										
										
											2020-10-08 16:48:11 -04:00
										 |  |  |     allocate (c00(0:nfft1-1))
 | 
					
						
							| 
									
										
										
										
											2020-08-08 13:57:24 -04:00
										 |  |  |     allocate (c0(0:nfft1-1))
 | 
					
						
							| 
									
										
										
										
											2020-08-09 11:04:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-08 09:14:12 -04:00
										 |  |  |     if(ntrperiod.eq.15) then
 | 
					
						
							|  |  |  |        nsps=1800
 | 
					
						
							|  |  |  |     else if(ntrperiod.eq.30) then
 | 
					
						
							|  |  |  |        nsps=3600
 | 
					
						
							|  |  |  |     else if(ntrperiod.eq.60) then
 | 
					
						
							| 
									
										
										
										
											2020-10-25 14:10:38 -04:00
										 |  |  |        nsps=7200
 | 
					
						
							| 
									
										
										
										
											2020-08-08 09:14:12 -04:00
										 |  |  |     else if(ntrperiod.eq.120) then
 | 
					
						
							|  |  |  |        nsps=16000
 | 
					
						
							|  |  |  |     else if(ntrperiod.eq.300) then
 | 
					
						
							|  |  |  |        nsps=41472
 | 
					
						
							|  |  |  |     else
 | 
					
						
							| 
									
										
										
										
											2020-10-09 14:12:34 -04:00
										 |  |  |        stop 'Invalid TR period'
 | 
					
						
							|  |  |  |     endif
 | 
					
						
							|  |  |  |     baud=12000.0/nsps
 | 
					
						
							|  |  |  |     df1=12000.0/nfft1
 | 
					
						
							| 
									
										
										
										
											2020-10-29 10:53:30 -04:00
										 |  |  |     this%callback => callback
 | 
					
						
							| 
									
										
										
										
											2020-10-09 14:12:34 -04:00
										 |  |  |     nFadingModel=1
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  | ! Set up the codewords for full-AP list decoding    
 | 
					
						
							|  |  |  |     call q65_set_list(mycall,hiscall,hisgrid,codewords,ncw) 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 09:52:47 -05:00
										 |  |  |     dgen=0
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  |     call q65_enc(dgen,codewords)         !Initialize the Q65 codec
 | 
					
						
							| 
									
										
										
										
											2020-10-09 14:12:34 -04:00
										 |  |  |     call timer('sync_q65',0)
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  |     call q65_sync(nutc,iwave,ntrperiod,mode65,codewords,ncw,nsps,      &
 | 
					
						
							|  |  |  |          nfqso,ntol,ndepth,lclearave,emedelay,xdt,f0,snr1,width,dat4,  &
 | 
					
						
							| 
									
										
										
										
											2020-12-29 16:41:48 -05:00
										 |  |  |          snr2,idec)
 | 
					
						
							| 
									
										
										
										
											2020-10-09 14:12:34 -04:00
										 |  |  |     call timer('sync_q65',1)
 | 
					
						
							| 
									
										
										
										
											2020-12-29 16:41:48 -05:00
										 |  |  |     if(idec.ge.0) then
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  |        xdt1=xdt                          !We have a list-decode result
 | 
					
						
							| 
									
										
										
										
											2020-11-30 09:52:47 -05:00
										 |  |  |        f1=f0
 | 
					
						
							| 
									
										
										
										
											2020-12-29 16:41:48 -05:00
										 |  |  |        go to 100
 | 
					
						
							| 
									
										
										
										
											2020-11-30 09:52:47 -05:00
										 |  |  |     endif
 | 
					
						
							|  |  |  |     
 | 
					
						
							| 
									
										
										
										
											2020-12-21 15:59:33 -05:00
										 |  |  |     if(snr1.lt.2.8) then
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  |        xdt1=0.                   !No reliable sync, abandon decoding attempt
 | 
					
						
							| 
									
										
										
										
											2020-12-21 15:59:33 -05:00
										 |  |  |        f1=0.
 | 
					
						
							|  |  |  |        go to 100
 | 
					
						
							|  |  |  |     endif
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  |     
 | 
					
						
							|  |  |  |     jpk0=(xdt+1.0)*6000                      !Index of nominal start of signal
 | 
					
						
							|  |  |  |     if(ntrperiod.le.30) jpk0=(xdt+0.5)*6000  !For shortest sequences
 | 
					
						
							| 
									
										
										
										
											2020-10-30 11:07:44 -04:00
										 |  |  |     if(jpk0.lt.0) jpk0=0
 | 
					
						
							|  |  |  |     fac=1.0/32767.0
 | 
					
						
							| 
									
										
										
										
											2020-11-15 12:21:08 -05:00
										 |  |  |     dd=fac*iwave(1:npts)
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  |     call ana64(dd,npts,c00)              !Convert to complex c00() at 6000 Sa/s
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Generate ap symbols as in FT8
 | 
					
						
							| 
									
										
										
										
											2020-10-30 11:07:44 -04:00
										 |  |  |     call ft8apset(mycall,hiscall,ncontest,apsym0,aph10)
 | 
					
						
							|  |  |  |     where(apsym0.eq.-1) apsym0=0
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  | ! Main decoding loop starts here
 | 
					
						
							| 
									
										
										
										
											2020-10-30 11:07:44 -04:00
										 |  |  |     npasses=2
 | 
					
						
							|  |  |  |     if(nQSOprogress.eq.5) npasses=3
 | 
					
						
							|  |  |  |     if(lapcqonly) npasses=1
 | 
					
						
							| 
									
										
										
										
											2020-11-11 15:06:24 -05:00
										 |  |  |     iaptype=0
 | 
					
						
							| 
									
										
										
										
											2020-10-30 11:07:44 -04:00
										 |  |  |     do ipass=0,npasses
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  |        apmask=0                         !Try first with no AP information
 | 
					
						
							| 
									
										
										
										
											2020-10-30 11:07:44 -04:00
										 |  |  |        apsymbols=0
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-30 11:07:44 -04:00
										 |  |  |        if(ipass.ge.1) then
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  |           ! Subsequent passes use AP information appropiate for nQSOprogress
 | 
					
						
							| 
									
										
										
										
											2020-11-11 15:06:24 -05:00
										 |  |  |           call q65_ap(nQSOprogress,ipass,ncontest,lapcqonly,iaptype,   &
 | 
					
						
							|  |  |  |                apsym0,apmask1,apsymbols1)
 | 
					
						
							| 
									
										
										
										
											2020-10-30 11:07:44 -04:00
										 |  |  |           write(c78,1050) apmask1
 | 
					
						
							|  |  |  | 1050      format(78i1)
 | 
					
						
							|  |  |  |           read(c78,1060) apmask
 | 
					
						
							|  |  |  | 1060      format(13b6.6)
 | 
					
						
							|  |  |  |           write(c78,1050) apsymbols1
 | 
					
						
							|  |  |  |           read(c78,1060) apsymbols
 | 
					
						
							| 
									
										
										
										
											2020-11-22 13:58:29 -05:00
										 |  |  |           if(iaptype.eq.4) then
 | 
					
						
							|  |  |  |              do j=1,3
 | 
					
						
							|  |  |  |                 ng15=32401+j
 | 
					
						
							|  |  |  |                 write(c78(60:74),'(b15.15)') ng15
 | 
					
						
							|  |  |  |                 read(c78,1060) dgen
 | 
					
						
							|  |  |  |                 call q65_enc(dgen,codewords(1,j))
 | 
					
						
							|  |  |  |              enddo
 | 
					
						
							|  |  |  |           endif
 | 
					
						
							| 
									
										
										
										
											2020-10-30 11:07:44 -04:00
										 |  |  |        endif
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-27 13:08:07 -04:00
										 |  |  |        call timer('q65loops',0)
 | 
					
						
							| 
									
										
										
										
											2020-12-28 18:53:13 -05:00
										 |  |  |        call q65_loops(c00,npts/2,nsps/2,mode65,nsubmode,ndepth,jpk0,   &
 | 
					
						
							| 
									
										
										
										
											2020-12-30 15:05:02 -05:00
										 |  |  |             xdt,f0,iaptype,xdt1,f1,snr2,dat4,idec)
 | 
					
						
							| 
									
										
										
										
											2020-10-27 13:08:07 -04:00
										 |  |  |        call timer('q65loops',1)
 | 
					
						
							| 
									
										
										
										
											2020-12-30 15:05:02 -05:00
										 |  |  |        if(idec.gt.0) go to 100       !Successful decode, we're done
 | 
					
						
							| 
									
										
										
										
											2020-10-30 11:07:44 -04:00
										 |  |  |     enddo
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  | ! No single-transmission decode.
 | 
					
						
							| 
									
										
										
										
											2020-12-29 16:41:48 -05:00
										 |  |  |     if(iand(ndepth,16).eq.16) then
 | 
					
						
							| 
									
										
										
										
											2020-12-30 12:10:03 -05:00
										 |  |  |        call q65_avg2(ntrperiod,ntol,baud,nsubmode,nQSOprogress,lapcqonly, &
 | 
					
						
							|  |  |  |             ibwa,ibwb,codewords,ncw,xdt,f0,snr1,snr2,dat4,idec)
 | 
					
						
							| 
									
										
										
										
											2020-12-29 16:41:48 -05:00
										 |  |  |     endif
 | 
					
						
							| 
									
										
										
										
											2020-12-28 18:53:13 -05:00
										 |  |  |     
 | 
					
						
							| 
									
										
										
										
											2020-10-30 11:07:44 -04:00
										 |  |  | 100 decoded='                                     '
 | 
					
						
							| 
									
										
										
										
											2020-12-29 16:41:48 -05:00
										 |  |  |     if(idec.gt.0) then
 | 
					
						
							| 
									
										
										
										
											2020-12-30 10:42:27 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! ------------------------------------------------------
 | 
					
						
							|  |  |  | ! idec Meaning
 | 
					
						
							|  |  |  | ! ------------------------------------------------------
 | 
					
						
							|  |  |  | ! -1:  No decode
 | 
					
						
							|  |  |  | !  1:  Decode with AP for "MyCall DxCall ?"
 | 
					
						
							|  |  |  | !  2:  Decode without AP information
 | 
					
						
							|  |  |  | !  3:  Decode with AP for "CQ ? ?"
 | 
					
						
							|  |  |  | !  4:  Decode with AP for "MyCall ? ?"
 | 
					
						
							|  |  |  | ! ------------------------------------------------------
 | 
					
						
							|  |  |  | ! Second digit (if any) is number of sequences averaged.
 | 
					
						
							|  |  |  | ! ------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-28 15:27:10 -05:00
										 |  |  | ! Unpack decoded message for display to user
 | 
					
						
							| 
									
										
										
										
											2020-11-11 15:06:24 -05:00
										 |  |  |        write(c77,1000) dat4(1:12),dat4(13)/2
 | 
					
						
							| 
									
										
										
										
											2020-10-27 13:08:07 -04:00
										 |  |  | 1000   format(12b6.6,b5.5)
 | 
					
						
							|  |  |  |        call unpack77(c77,0,decoded,unpk77_success) !Unpack to get msgsent
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  |        nsnr=nint(snr2)
 | 
					
						
							| 
									
										
										
										
											2021-01-05 11:30:22 -05:00
										 |  |  |        call this%callback(nutc,sync,nsnr,xdt1,f1,decoded,idec,ntrperiod)
 | 
					
						
							|  |  |  |        call q65_clravg
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  |     else
 | 
					
						
							| 
									
										
										
										
											2020-11-02 15:59:10 -05:00
										 |  |  | ! Report sync, even if no decode.
 | 
					
						
							| 
									
										
										
										
											2020-10-27 16:08:50 -04:00
										 |  |  |        nsnr=db(snr1) - 35.0
 | 
					
						
							| 
									
										
										
										
											2020-11-30 14:13:37 -05:00
										 |  |  |        idec=-1
 | 
					
						
							| 
									
										
										
										
											2020-11-13 13:40:16 -05:00
										 |  |  |        call this%callback(nutc,sync,nsnr,xdt1,f1,decoded,              &
 | 
					
						
							| 
									
										
										
										
											2020-11-30 13:14:18 -05:00
										 |  |  |             idec,ntrperiod)
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  |     endif
 | 
					
						
							| 
									
										
										
										
											2020-08-01 15:12:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-01 09:24:59 -04:00
										 |  |  |     return
 | 
					
						
							|  |  |  |   end subroutine decode
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-25 13:58:18 -04:00
										 |  |  | end module q65_decode
 |