!****************************************************************
!*                                                              *
!*         Little program reads frames from the SEESCAN board   *
!*                                                              *
!*                  Version 1.2   30 Dec 1986                   *
!*                                                              *
!****************************************************************

! Qsart routines pared to bare minimum.  See AJS:QSART etc for full version

%option "-nolist"
%include "fractl:iffutils"
%constinteger ht = 256, wid = 256, ibyte=0
%conststring (1) quotes=""""

%Begin

%string(255) file, s1,s2
%integer msec, rc,c1,i,j,k,yn
%byte %array image, stretch(0:65535)
%constant %integer boardaddr = 16_7FFA0    ;! Change as appropriate
%recordformat DEVICE FM(%byte bstatus,data,intvec,dstatus,x,mode,y,command)
@boardaddr %record(device fm) device
%record (iffhdr fm) iffhdr

! baudrates(0:15)
! 46,50,75,110,135,150,300,600,1200,1800,2000,2400,4800,9600,19200,38400

%routine set baud(%integer code)
  %constinteger mode1=16_4e,mode2=16_30,comm=16_37,reset=8

  %on 0 %start
     Printline("**Bus error.") %unless event_sub=1
     %stop
  %Finish

  device_bstatus = reset; device_bstatus = 0
  device_mode = mode1;    device_mode = mode2+code
  device_dstatus = 0;     device_dstatus = 0
  device_dstatus = 0;     device_command = comm
%end

%routine put(%Integer sym)
   %While device_dstatus&1=0 %cycle; %repeat
   device_data =sym
%End


%routine putstring(%string (255) s)
   %integer i
   %return %if s=""
   %for i=1,1,length(s) %cycle; put(charno(s,i)); %repeat
%end


%routine pause(%integer msec)
   msec = msec + cputime
   %cycle; %repeatuntil cputime>=msec
%end

%routine hands on
   %integer c1,ptr,ctrl
   %bytearray buffer(0:63)
   !Transparent terminal.  Note APM switches cr and lf so we switch them back
   !rather than having to fiddle with EXEMPT MASK.  
   !Output to Seescan is buffered.  Output to VDU is not.

   printline("In Hands-on mode - ctrl-Z to exit")
   put(13)

   ptr=0
   %cycle
      ctrl = device_dstatus
      %if ctrl&2 # 0 %start
         c1 = device_data
         printsymbol(c1)
      %finish
      %if ctrl&1 # 0 %and ptr#0 %start
         ptr=ptr-1; device_data=buffer(ptr)
      %finish

      c1=testsymbol
      %if c1>=0 %start
         %exit %if c1=16_1A ;!Ctrl-Z
         %if c1=13 %or c1=10 %then c1=23-c1 %elsestart
            %if 'a'<=c1<='z' %then c1=c1-'a'+'A'
         %finish
         buffer(ptr)=c1; ptr=ptr+1
      %finish
   %repeat
%end

! Nicked from MET EDITH package..
! Aspect ratio of pictures should be 4:3 NOT 1:1 (x:y)
! The correct aspect ratioing is achieved by taking 4 points numbered
! (0,1,2,3) & interpolating them to points (0,1+1/3,2+2/3)
! o(A0) contains start addr of output line
! t(A1) contains start addr of current picture line
%routine alter aspect(%bytename o,t)

  *move.w #255,d0;!      Loop for all lines in origrinal picture
a:*move.w #63,d1;!       Loop for the 64 sets of 4 pts vertically
  *move.l a0,a2;!        Preserve addresses
  *move.l a1,a3
b:*move.b (a3),(a2);!    Copy current pt 0 to new pt 0
  *clr.l d2;!            Clear working registers
  *clr.l d3
  *clr.l d4
  *move.b 512(a3),d2;!   Get pt 1 one line up from pt 0(ie 512 bytes)
  *move.b 1024(a3),d3;!  Get pt 2 two lines up from pt 0
  *move.b 1536(a3),d4;!  Get pt 3 three lines up from pt 0
  *lsl.w  #1,d2;!        Multiply pt 1 by two (weighting factor in interpolation)
  *lsl.w  #1,d4;!        Multiply pt 3              ""           ""
  *add.w  d3,d2;!        Add in pt 2 to new pt 1
  *add.w  d3,d4;!        Add in pt 2 to new pt 3
  *divu   #3,d2;!        Divide by 3 to obtain pt 1+1/3
  *divu   #3,d4;!        Divide by 3 to obtain pt 2+2/3
  *move.b d2,512(a2);!   Store 1+1/3 one line up from current output point
  *move.b d4,1024(a2);!  Store 2+2/3 two lines up from current output point
  *adda.l #1536,a2;!     Move output pointer up three lines
  *adda.l #2048,a3;!     Move input pointer up four lines
  *dbra d1,b;!           Loop to do next group of 4 pts
  *adda.l #1,a0;!        Move output 1 place horizontally
  *adda.l #1,a1;!        Move input  1 place horizontally
  *dbra d0,a;!           Loop to do next vertical line

%end

%option "-list"
%routine grab image(%integer imaddr)
   %integer n,len,i,csum,offset,junk

   %integerfn get
!!     %while device_dstatus&2=0 %cycle; %Repeat
!!     %Result = device_data

       %label l1
L1:    *BTST.b  #1,16_0007FFA3
       *beq     l1
       *clr.l   d0
       *move.b  16_0007FFA1,d0
       *rts
   %end


   %bytefn gethex2
      !Seescan produces 7-bit ASCII (observed)
      !Get next two hex nibbles as a byte and add it to checksum
      %label l1,l2,l3
       *clr.l   d0
L1:    *BTST.b  #1,16_0007FFA3
       *beq     l1 
       *move.b  16_0007FFA1,d0
       *ADDi.b  #-48,D0
       *CMPi.b  #9,D0
       *BLE     L2 
       *ADDQ.b  #7,d0
   
L2:    *BTST.b  #1,16_0007FFA3
       *beq     l2 
       *move.b  16_0007FFA1,d1
       *ADDi.b  #-48,D1
       *CMPi.b  #9,d1
       *BLE     L3 
       *ADDQ.b  #7,d1
   
L3:    *LSL.b   #4,D0
       *ADD.b   d1,D0
       *ADD.b   D0,csum
   
       *RTS     
   %end
   
   %integerfn gethex4
      !! %result=gethex2<<8+gethex2
      *BSR     gethex2
      *move.w  d0,d2
      *lsl.w   #8,d2
      *BSR     gethex2
      *ADD.w   d2,d0
   %end
   
   n=0
   %cycle
     %if get=':' %start
       csum=0
       len=gethex2
       offset=gethex4 ;!Don't use offset
       junk=gethex2 ;!Add to checksum
       %for i=len-1,-1,0 %cycle
          byteinteger(imaddr+n) = gethex2; n=n+1
       %repeat
       junk=gethex2 ;!add checksum to accumulated checksum
     %finish
   %repeatuntil n=65536
%end

%option "-nolist"
set terminal mode(8)
set baud(13) ;!9600
file = cliparam
printline("** WARNING - NO OUTPUT FILE SPECIFIED - SEESCAN.IFF ASSUMED **") %if file = ""
!Append an IFF extension if no extension provided
file="seescan" %if file=""
file = file.".iff" %unless file -> s1.(".").s2

!Poll until transmitting a <return> provokes a '>' prompt.
c1=0
%cycle
   put(27)
   put(13)
   msec = cputime + 2000
   %cycle
      %if device_dstatus&2 # 0 %start
         c1 = device_data & 16_7F
      %finish
   %repeatuntil cputime>=msec %or c1 = '>'
   printline("Polling for Seescan board")
%repeatuntil c1 = '>'
printline("Seescan board groped OK")
hands on
printstring("Capturing Frame")

iffhdr=0
putstring("FREEZE"); put(13); put(10)
newline
prompt("Image Title:"); readline(iffhdr_title)
prompt("Adjust aspect ratio?")
readsymbol(yn) %until yn='Y' %or yn='y' %or yn='N' %or yn='n'
yn=yn & 16_5f
yn='N'
pause(500)
putstring("SAVE ".quotes."FILE".quotes." S"); put(13); put(10)
!!putstring("BAUDRATE -1:SAVE ".quotes."FILE".quotes." S"); put(13); put(10)
!!pause(1)
!!set baud(15)

grab image(addr(image(0)))

newline

rc = iff open file(file, iffhdr, iff write)

iffhdr_ht    = ht
iffhdr_ht    = (iffhdr_ht//4)*3 %if yn='Y'
iffhdr_wid   = wid
iffhdr_id    = 002436 ;!Serial no. of Seescan camera
iffhdr_fstop = 140    ;!f/1.4
iffhdr_focus = 16     ;!16mm
iffhdr_title = "Seescan image - ".iffhdr_title
iffhdr_aspect= 16_0403;!rectangular pixels x=4 y=3

rc=iff write header(iffhdr)

%if yn='Y' %start
   alter aspect(image(0), stretch(0)) 
   %for i=0,1,ht*wid-1 %cycle; printsymbol(stretch(i)); %repeat
%else
   %for i=0,1,65535 %cycle; printsymbol(image(i)); %repeat
%finish
iff close file(iffhdr)
%endofprogram

