!******************************************************************************!
!                                                                              !
!                                  ROBOT VISION                                !
!                                                                              !
!                               IAN R GEBBIE (CS4)                             !
!                                                                              !
! incorporating later hacks by Brian Craigie, Dave Baines, and Julian Turnbull !
!                                                                              !
!******************************************************************************!
%option "-nons-nowarn"

! The following declaration is to allow space to be allocated from the heap
! to hold the lookup table used in unscrambling the geometry of the image.
%record %format trfm (%integer %array tr(0:128,0:255))
%own %record (trfm) %name transfer

%include "inc:util.imp"
%include "camera:region.inc"
%include "inc:level1.imp"

%constinteger  tag = 16_C0,
               noalt=32,
               narrow=16,
               eightbit=8,
               twoarray=4,
               soak=2,
               nosend=1,
               alt=0,
               wide=0,
               sevenbit=0,
               onearray=0,
               refresh=0,
               send=0
               
!Zapped interface addresses
!%constinteger base = 16_400FF0

!BEPI interface addresses (Thanks Rainer)
%constinteger base = 16_400600

@base+16_00 %byte acia cont;  @base+16_02 %byte acia data

!******************************************************************************!
!                                  WAIT                                        !
!******************************************************************************!
%routine wait(%integer msec)
   msec = cputime + msec
   %while cputime <= msec %cycle
   %repeat
%end

!******************************************************************************!
!                                  OPEN ACIA                                   !
!******************************************************************************!
%bytefn inv8(%byte i)
   %constintegerarray inv(0:15)= %c
   16_00,16_08,16_04,16_0C,16_02,16_0A,16_06,16_0E,
   16_01,16_09,16_05,16_0D,16_03,16_0B,16_07,16_0F
   %result = inv(i&15)<<4+inv(i>>4&15)
%end

%routine puta(%integer ad, %byte val)
   !Inverts the bit order of a byte
   byte(ad) = inv8(val)
%end

%bytefn geta(%integer ad)
   !Inverts bit order
   %result = inv8(byte(ad))
%end
   

%routine open acia
   %constinteger acset = 16_03, {master reset}
                 acopt = 16_14  {div 1, 8 bits 1 stop bit}
   puta(acia cont, acset)
   puta(acia cont, acopt)
%end

!******************************************************************************!
!                                  OUTCH                                       !
!******************************************************************************!
%routine outch(%integer ch)
   %integer c, time
   time=cputime+1000
   %cycle
       c = acia cont
       %exit %if c&16_40 # 0 ;!Inverted
!       %signal 15,1 %if time=cputime
       %signal 15,1 %if time >= cputime  {BSC !}
   %repeat
   puta(acia data, ch)
%end


!******************************************************************************!
!                                  GRAB FRAME                                  !
!******************************************************************************!
%routine grab frame (%integer command, exposure, address,
                     %integername rows,cols,bytes)

      %integer start, end, i
      %label waitch
      open acia
      wait(2)
      command = (command & (\3)) ! tag ! refresh ! nosend
      outch(command)

      wait(5)
      
      command = (command & (\3)) ! soak ! nosend
      outch(command)

      wait(exposure)
      rows=64; cols=16
      command = (command & (\3)) ! send ! noalt ! refresh
   {*** The above line altered so that the exposure can be set by the user ***}
   {*** Old version was:                                                   ***}
   !  command = (command & (\3)) ! send ! noalt ! soak
   {***                                          JST, 5/1/87               ***}

      %if command & twoarray # 0 %then rows=rows*2
      %if command & narrow = 0   %then cols=cols*2
      %if command & noalt # 0 %then    rows=rows*2 %and cols=cols*2
      bytes=rows*cols

      outch(command)

    start = address; end = address+bytes
 
    *movea.l start,a0
    *movea.l end,a1
 
 waitch:
    *btst    #7,aciacont   ;!Note inverted
    *beq     waitch
    *move.b  aciadata,0(a0)
    *adda.l  #1,a0
    *cmpa.l   a0,a1
    *bne     waitch
 
     %for i = address, 1, address+bytes-1 %cycle
        byte(i) = inv8(byte(i))
     %repeat
     command = (command & (\3)) ! nosend ! refresh
     outch(command)
 %end

!--------------------------------- plot frame ----------------------------------

! plot frame => Plot image frame with left hand bottom corner at given coords.
   %EXTERNALROUTINE plot frame %alias "PLOT_FRAME" ( %INTEGER pic,
                                 %BYTEARRAYNAME snap ( 0:128, 0:513 ) )

!---------------------------------- clear box ----------------------------------

! clear box => Clear the inside of the frame plotting box
   %ROUTINE clear box ( %INTEGER pic )

! Local Variables :
   %INTEGER ycorner

! Begin clear box
   %IF ( pic = 0 ) %THEN ycorner = 1 %ELSE ycorner = 141
   colour ( black ) ;
   fill ( 87, ycorner, 600, ycorner+128 )

   %END ; ! of routine clear box -----------------------------------------------

! Local Variables :
   %INTEGER row, column, offset, row1, rowoffset

! Begin plot frame

   %IF ( pic = 0 ) %THEN rowoffset = 129 %ELSE rowoffset = 269
   clear box ( pic )
   colour ( white ) ;
   %FOR row = 0, 1, 128 %CYCLE
      row1 = rowoffset - row
      %FOR column = 0, 1, 513 %CYCLE
         %IF ( snap ( row, column ) = 1 ) %THEN plot(column+87, row1) ;
      %REPEAT
   %REPEAT

   %END ; ! of routine plot frame ----------------------------------------------

!---------------------------------- clear snap----------------------------------

! clear snap => Set whole of snap array to zero's
   %ROUTINE clear snap ( %BYTEARRAYNAME snap ( 0:128, 0:513 ) )

! Local Variables :
   %INTEGER x, y

! Begin clear snap

   %FOR x = 0, 1, 128 %CYCLE
      %FOR y = 0, 1, 513 %CYCLE
         snap ( x, y ) = 0
      %REPEAT
   %REPEAT

   %END ; ! of routine clear snap ----------------------------------------------

%EXTERNALROUTINESPEC fast transform ( %BYTENAME packed, %BYTENAME snap,
                                      %RECORD(TRFM)%NAME transfer )

!--------------------------------- raw to snap ---------------------------------

! raw to snap => Convert raw data frame to a snap frame
   %ROUTINE raw to snap ( %BYTEARRAYNAME pic ( 0:65535 ),
                          %BYTEARRAYNAME snap ( 0:128, 0:513 ) )

! Local Variables :
   %INTEGER start, finish, duration

! Begin raw to snap

   start = cputime

! perform packed raw data -> snap frame transformation using lookup table
   fast transform ( pic ( 0 ), snap ( 0, 0 ), transfer)

   finish = cputime
   duration = finish - start
!   PRINTSTRING ( "Duration = " ) ; WRITE ( duration, 6 ) ; NEWLINE

   %END ; ! of routine raw to snap ---------------------------------------------

!------------------------get_frame---------------------------------------------
!
%externalroutine get frame %alias "GET_FRAME" (%integer exposure,
                                  %bytearrayname pic(0:128,0:513))

%bytearray rawpic(0:65535)
%integer command,actbytes,rows,cols

   command=noalt ! narrow ! eightbit ! onearray

   grab frame(command,exposure,addr(rawpic(0)),rows,cols,actbytes)
   raw to snap(rawpic,pic)

%end {get_frame}

!--------------------------------- filter snap ---------------------------------

! filter snap => Apply a filter to the image image.
   %EXTERNALROUTINE filter snap %alias "FILTER_SNAP" %c
                                ( %BYTEARRAYNAME snap ( 0:128, 0:513 ),
                                  %BYTEARRAYNAME fsnap ( 0:128, 0:513 ) )

! Local Variables :
   %INTEGER row, column, sum, rowp1, rowm1, colp1, colm1
   %INTEGER start, finish, duration

! Begin

   start = cputime

   %FOR column = 0, 1, 513 %CYCLE
      fsnap ( 0, column ) = snap ( 0, column )
      fsnap ( 128, column ) = snap ( 128, column )
   %REPEAT

   %FOR row = 1, 1, 127 %CYCLE
      fsnap ( row, 0 ) = snap ( row, 0 )
      %FOR column = 1, 1, 512 %CYCLE
         rowp1 = row + 1
         rowm1 = row - 1
         colp1 = column + 1
         colm1 = column - 1
         sum = snap( rowm1,colm1 ) + snap( rowm1,column ) + snap( rowm1,colp1 )
         sum = sum + snap( row,colm1 ) + snap( row,column ) + snap( row,colp1 )
         sum = sum + snap(rowp1,colm1) + snap(rowp1,column) + snap(rowp1,colp1)
         %IF ( sum > 2 ) %THEN fsnap ( row, column ) = 1 %C
         %ELSE fsnap ( row, column ) = 0
      %REPEAT
      fsnap ( row, 513 ) = snap ( row, 513 )
   %REPEAT
   finish = cputime
   duration = finish - start
   PRINTSTRING ( "Filter duration = " ) ; WRITE ( duration, 6 ) ; NEWLINE ;

   %END ; ! of routine filter snap ---------------------------------------------

!*****************************************************!
!         FILLIMAGE                                   !
!  Routine fills out blank values in image array.     !
!  If blank pixel has two or more neighbours set to 1 !
!  then set pixel to a 1 as well                      !
!*****************************************************!
%externalroutine fillim %alias "FILL_IMAGE" (%bytearrayname image(0:128,0:513))
%integer row,col
%mitearray neighbours(1:127,1:512)

   print string("Filling of image started - please be patient".snl)

   %for row=1,1,127 %cycle
      %for col=1,1,512 %cycle
         %if image(row,col)=0 %then neighbours(row,col)=0 %else %c
         neighbours(row,col)=(image(row-1,col-1)&1)+(image(row-1,col+1)&1) %c
                            +(image(row+1,col-1)&1)+(image(row+1,col+1)&1)
      %repeat
   %repeat

   %for row=1,1,127 %cycle
      %for col=1,1,512 %cycle
         %if neighbours(row,col)>1 %then image(row,col)=1
      %repeat
   %repeat

%end


!-------------------------------- init transfer --------------------------------

! init transfer => Initialse the raw data -> image data transfer array.
   %EXTERNALROUTINE init transfer %ALIAS "INIT_CAMERA"

! Local Variables :
   %INTEGER row, column, x, index, temp, offset

! Begin init transfer
! Get space for lookup table from heap
   transfer==new(transfer)

! edge pixels first
   %FOR row = 0, 2, 126 %CYCLE
      offset = ( row * 514 ) + 513
      transfer_tr ( row, 0 ) = offset + 1
      transfer_tr ( row, 255 ) = offset
   %REPEAT

! even row pixels
   %FOR row = 0, 2, 126 %CYCLE
      %FOR column = 1, 2, 253 %CYCLE
         x = column * 2
         offset = ( row * 514 ) + x
         transfer_tr ( row, column ) = offset
         transfer_tr ( row, column+1 ) = offset + 519
      %REPEAT
   %REPEAT

! odd row pixels
   %FOR row = 1, 2, 127 %CYCLE
      %FOR column = 0, 2, 254 %CYCLE
         x = column * 2
         offset = ( row * 514 ) + x
         transfer_tr ( row, column ) = offset
         transfer_tr ( row, column+1 ) = offset + 519
      %REPEAT
   %REPEAT

   %END ; ! of routine init transfer -------------------------------------------


!******************************************************************************!
!                          INIT DISPLAY                                        !
!******************************************************************************!
%external %routine init display %alias "INIT_DISPLAY"

!------------------------------- plot box border -------------------------------

! plot box border => Plot the border for the frame plotting box
   %ROUTINE plot box border ( %INTEGER pic )

! Local Variables
   %INTEGER ycorner

! Begin plot box border
   %IF ( pic = 0 ) %THEN %START
      colour ( blue ) ;
      ycorner = 0
   %FINISH %ELSE %START
      colour ( red ) ;
      ycorner = 140
   %FINISH

   hline(86,601,ycorner)
   hline(86,601,ycorner+130)
   vline(86,ycorner,ycorner+130)
   vline(601,ycorner,ycorner+130)

   %END ; ! of routine plot box border -----------------------------------------

! clear graphics screen
   clear

! plot image box borders
   plot box border ( 0 )
   plot box border ( 1 )

%end {init display}

%endoffile
