divert(-1) dnl +------------------------------------------------------------------------+ dnl | SYNDEX Camera Kernel V7.0 | dnl | | dnl | Author : Marc.Chappellier@inria.fr | dnl | History: SYNDEX FUNCTIONS | dnl | EXPOSURE CONTROL | dnl | PHASE LOOP LOCK CONTROL | dnl | SPOT FOLLOWING | dnl | WINDOW ON THE TARGET AND SEMANTIC OF THE TARGET | dnl | IGNORE ALL PARASIT SPOTS | dnl | TRIGGER LEVELS MOVING FOR DETECT PHASE | dnl +------------------------------------------------------------------------+ dnl +------------------------------------------------------------------------+ dnl | Declaration of utils macros | dnl +------------------------------------------------------------------------+ dnl comment{comments with balanced curly braces}comment dnl define(`comment_', `changequote({,})patsubst({{$1}}, {^}, {; })changequote') define(`comment_') define(`comment', `pushdef(`comment', `changequote)`'popdef(`comment') dnl')changequote({,})comment_(') dnl Use this defining macro to generate a trace in the output define(`def',`define(`$1', ` ; --> ' changequote([,])[`$][0($][@) <--']changequote `$2')') dnl Use this one if no trace is wanted in the output: dnl define(`def',`define(`$1', `$2')') dnl forloop(variable,start value,end value,function) define(`forloop',`pushdef(`$1',`$2')_forloop(`$1',`$2',`$3',`$4')popdef(`$1')') define(`_forloop',`$4`'ifelse($1,`$3',,`define(`$1',incr($1))dnl _forloop(`$1',`$2',`$3',`$4')')') dnl reverse(arg1,arg2,arg3,..) --> arg3,arg2,arg1 define(`reverse', `ifelse($#,0,,$#,1,``$1'',`reverse(shift($@)),`$1'')') dnl +------------------------------------------------------------------------+ dnl | Declaration of divert numbers | dnl +------------------------------------------------------------------------+ define(`DIVUNI',`1') dnl divert number for datas uninitialized define(`DIVCST',`2') dnl divert number for constants define(`DIVINI',`3') dnl divert number for initializing datas dnl +------------------------------------------------------------------------+ dnl | Declaration of the macro "processor" | dnl +------------------------------------------------------------------------+ dnl processor(name) define(`processor_',`` PROG_CAM MODULE MAIN,STACKSIZE(8) ; +--------------------------------------------------------------------------+ ; | Static variables definitions | ; +--------------------------------------------------------------------------+ ; ** SFR Registers definitions ** ad_comma equ 00002h : byte ad_resul equ 00002h : word ad_re_hi equ 00003h : byte ad_time equ 00003h : byte hsi_mode equ 00003h : byte hsi_time equ 00004h : word hso_time equ 00004h : word ptssel equ 00004h : word hsi_stat equ 00006h : byte hso_comm equ 00006h : byte ptssrv equ 00006h : word sbufrx equ 00007h : byte sbuftx equ 00007h : byte int_mask equ 00008h : byte int_pend equ 00009h : byte timer1 equ 0000Ah : word watchdog equ 0000Ah : byte ioc2 equ 0000Bh : byte timer2 equ 0000Ch : word ioc3 equ 0000Ch : byte port0 equ 0000Eh : byte baud_rat equ 0000Eh : byte port1 equ 0000Fh : byte port2 equ 00010h : byte sp_stat equ 00011h : byte sp_con equ 00011h : byte int_pen1 equ 00012h : byte int_mas1 equ 00013h : byte wsr equ 00014h : byte ios0 equ 00015h : byte ioc0 equ 00015h : byte ios1 equ 00016h : byte ioc1 equ 00016h : byte pwm1_con equ 00016h : byte ios2 equ 00017h : byte pwm0_con equ 00017h : byte pwm2_con equ 00017h : byte sp equ 00018h : word ; ** Serial definitions ** RS_IRQ equ 0800Ch ; Address of SERIAL IT vector RS_SLEEP equ 00000h ; Value for mode sleep RS_RECEIVE equ 00001h ; Value for mode receive RS_RTR_SENT equ 00002h ; Value for mode RTR sent RS_WAIT_RTR equ 00003h ; Value for mode wait RTR RS_TRANSMIT equ 00004h ; Value for mode transmit RS_RTR_RECEIVED equ 00005h ; Value for mode RTR already received ; ** Camera definitions ** LED1 equ 00001h ; Bit number for LED 1 LED2 equ 00002h ; Bit number for LED 2 MOCO equ 00200h ; Address of command word COMA equ 00202h ; Address of action word LIM1 equ 0020Ch ; Address of trigger min level LIM2 equ 0020Eh ; Address of trigger max level FIFO equ 00220h ; Address of FIFO START_LINE_IRQ equ 08006h ; Address of HSO IT vector END_LINE_IRQ equ 0803Ah ; Address of EXTINT1 IT vector ; ** Control definitions (zero,expo,target following) ** TPER_TYP equ 00E87h ; Standart line period=5ms EXPO_MIN equ 00001h ; Minimum exposure time EXPO_MAX equ 00230h ; Maximum exposure time=750†s EXPO_OK equ 00F00h ; Optimal maximum for exposure EXPO_DT equ 00080h ; Delta +/- accepted on EXPO_OK NB_VPR_LINES equ 003E8h ; Nb lines to control zero at beginning (5 s) NB_ZERO_LINES equ 000C8h ; Nb lines to control zero reference (1 s) NB_EXPOS_INIT equ 000C8h ; Exposure control at beginning (1 s) NB_EXPOS equ 000C8h ; Exposure normal control length NB_MAX_SPOTS equ 0000Ah ; Nb max spots read in FIFO NB_MIN_FOUNDS equ 0000Ah ; Nb good flash to find NB_PIXELS equ 007FFh ; Nb pixels of the ccd WIDTH_PARASIT_SPOT equ 00001h ; Width max of a parasit spot WINDOW_MARGE equ 00014h ; Marge in pixels of the window SPOT_MARGE equ 00004h ; Marge in pixels of the window for each spot LOW_LEVEL equ 00100h ; Low level for FIFO trigger HIGH_LEVEL equ 00FFFh ; High level for FIFO trigger STEP_LEVEL equ 0000Ah ; Step level for target search EPSILON_MIN equ 00002h EPSILON_MAX equ 00010h ; ** FIFO definition ** FIFO_MIDLE equ 00004h ; Bit set if FIFO is half full FIFO_FULL equ 00005h ; Bit set if FIFO is full FIFO_EMPTY equ 00006h ; Bit set if FIFO is empty FIFO_BYTE equ 00007h ; Bit set if the byte readed is 1st FIFO_TRIG1 equ 00004h ; Bit set if signal accross level on FIFO_TRIG2 equ 00005h ; Bit set if signal accross level two FIFO_UP equ 00006h ; Bit set if signal accross by top FIFO_END equ 00007h ; Bit set if the byte readed is last ; ** FLAGS definition ** EXPO_ALREADY_MADE equ 00000h ; Bit number to control exposure command INIT_PHASE equ 00001h ; Bit number for init phase actived MAXDIF_MEASURE equ 00002h ; +--------------------------------------------------------------------------+ ; | Macros definitions | ; +--------------------------------------------------------------------------+ SONDE MACRO reg,data st reg,data ENDM PULSE MACRO bit xorb port1,bit xorb port1,bit ENDM START_MEASURE MACRO push timer2 ENDM END_MEASURE MACRO reg pop reg sub reg,timer2 neg reg ENDM ; +--------------------------------------------------------------------------+ ; | Declaration of registers | ; +--------------------------------------------------------------------------+ RSEG at 30h ; ** Syndex registers ** com_state : dsw 1 com_dma_size : dsw 1 com_dma_iptr : dsw 1 com_dma_addr : dsw 1 sem : dsl 2 ; ** Common registers ** ax : dsw 0 axlo : dsb 1 axhi : dsb 1 bx : dsw 0 bxlo : dsb 1 bxhi : dsb 1 cx : dsw 0 cxlo : dsb 1 cxhi : dsb 1 dx : dsw 0 dxlo : dsb 1 dxhi : dsb 1 d0 : dsl 0 d0lo : dsw 1 d0hi : dsw 1 ; ** Interruptions registers ** it_ax : dsw 0 ; Register ax it_axlo : dsb 1 it_axhi : dsb 1 it_bx : dsw 0 ; Register bx it_bxlo : dsb 1 it_bxhi : dsb 1 it_cx : dsw 0 ; Register cx it_cxlo : dsb 1 it_cxhi : dsb 1 it_dx : dsw 0 ; Register dx it_dxlo : dsb 1 it_dxhi : dsb 1 it_ex : dsw 0 ; Register ex it_exlo : dsb 1 it_exhi : dsb 1 it_fx : dsw 0 ; Register fx it_fxlo : dsb 1 it_fxhi : dsb 1 it_gx : dsw 0 ; Register gx it_gxlo : dsb 1 it_gxhi : dsb 1 it_d0 : dsl 0 ; Register d0 it_d0lo : dsw 1 it_d0hi : dsw 1 it_d1 : dsl 0 ; Register d1 it_d1lo : dsw 1 it_d1hi : dsw 1 it_end_jmp : dsw 1 ; Jumper to end of line functions ; ** Camera control registers ** flags : dsw 1 ; Flags for special functions max_ccd : dsw 1 ; Maximum of CCD line num_line : dsl 0 ; Number of line num_linelo : dsw 1 num_linehi : dsw 1 zero_count : dsw 1 ; Counter for zero control smin : dsw 1 ; Trigger Min level register smax : dsw 1 ; Trigger Max level register tper : dsw 1 ; Line period register ; ** EXPO registers ** expo : dsw 1 ; Exposure time expo_no : dsw 1 ; No-exposure time expo_count : dsw 1 ; Counter for exposure lines expo_lum : dsw 1 ; Maximum for exposure calc expo_jmp : dsw 1 ; Jumper to exposure functions ; ** SPOTS FOLLOW registers ** sp_gra1 : dsw 1 sp_pos1 : dsw 1 sp_grb1 : dsw 1 sp_gra2 : dsw 1 sp_pos2 : dsw 1 sp_grb2 : dsw 1 sp_maxi : dsw 1 filt_trig : dsw 1 nb_spots : dsw 1 ; Nb spots detected nb_founds : dsw 1 ; Nb targets found win_start : dsw 1 ; Start pixel of window win_end : dsw 1 ; End pixel of window max_spots : dsw 1 ; Minimum grayscale of good spots fifo_trig : dsw 1 ; short differential max trig_max : dsw 1 CSEG at 8080h ljmp main_ ; +--------------------------------------------------------------------------+ ; | PROG_INI_ | ; | | ; | This routine initializes the camera. | ; | INPUTS: Nothing. | ; | OUTPUTS: Nothing. | ; +--------------------------------------------------------------------------+ prog_ini_: ; Disable all ITs ; --------------- di clrb wsr ldb ioc2,#80h ; Clear CAM clrb int_mask ; Masks all ITs clrb int_mas1 clrb int_pend clrb int_pen1 ; Clear all pending ITs ; Send OK Message for loader ; -------------------------- jbc sp_stat,3,$ ldb sbuftx,#79 ; Send a "O" char ldb sbuftx,#75 ; Send a "K" char jbc sp_stat,3,$ ; Init Vector table ; ----------------- ld ax,#it_nul_ ld bx,#8000h init_vectors_: st ax,[bx]+ jbs bxlo,6,init_vectors_end_ jbc bxlo,4,init_vectors_ jbs bxlo,5,init_vectors_ add bx,#20h sjmp init_vectors_ init_vectors_end_: ; Init Camera ; ----------- ld ax,#1h ; Get variable exposition st ax,MOCO ; and measure of absolute max ld ax,#20h ; Synchro between Altera clock and 196 st ax,COMA ld ax,#40h ; Init Parity for differential max st ax,COMA ldb axlo,#80h ; Reset FIFO stb axlo,FIFO ; Init Semaphores ; --------------- ld sem+0,0 ld sem+2,0 ld sem+4,0 ld sem+6,0 ; RS232 Initialization ; -------------------- ldb sp_con,#9h ; Choose Asynchrone Mode No1 ldb baud_rat,#0Ch ; BaudRate=57600 bauds ldb baud_rat,#080h ldb com_state,#(1 SHL RS_SLEEP) ld ax,#it_com_ ; Init RS232 interrupt vector st ax,RS_IRQ orb int_mask,#40h ; Enable Serial RX/TX IT ; Init End of line interrupt ; -------------------------- ld ax,#it_end_line_ ; Init of EXTINT1 vector st ax,END_LINE_IRQ orb int_mas1,#20h ; Enable EXTINT1 IT ; Init HSO interrupt ; ------------------ andb port1,#0FFh-LED1 ; Set Command of flash low (0V) ldb wsr,#1 ; Internal Clock pour Timer 2 ldb ioc3,#1 ldb wsr,#15 ; Set HSO.0 to high (+5V) ldb ios0,#1 clrb wsr ; Reset timer 2 ldb ioc0,#2 ldb hso_comm,#050h ; One CAM HSO to clear HSO.0 ld hso_time,#TPER_TYP ; each TPER_TYP and a start of line IT ldb hso_comm,#04Eh ; One CAM HSO to reset timer 2 ld hso_time,#TPER_TYP ld ax,#it_start_line_ ; Init of HSO IT vector st ax,START_LINE_IRQ orb int_mask,#08h ; Enable HSO IT ; Init variables ; -------------- clr flags ; Flag initialization orb flags,#(1 SHL INIT_PHASE) clr num_linelo ; Clear number of line clr num_linehi clr zero_count ; Clear zero counter for VPR clr max_ccd ; Clear max of CCD clr nb_founds ; Clear nb founds target clr nb_spots ; Clear number of spots ld smin,#0FFFh ; Trigger level at maximum ld smax,#0FFFh ld expo,#EXPO_MIN ; Exposure time to minimum ld expo_no,#TPER_TYP-EXPO_MIN ld expo_count,#NB_EXPOS_INIT ; Init counter for exposure lines ld tper,#TPER_TYP ; Init time period of lines ld expo_jmp,#expo_get_max_ ; Init EXPO jumper ld it_end_jmp,#it_zero_ ; Init IT jumper clr win_start ; Init window ld win_end,#NB_PIXELS st 0,syndex_data + 2*0 ; Clear number of spots st 0,syndex_data + 2*1 ; Clear position of spot No1 st 0,syndex_data + 2*2 ; Clear position of spot No2 st 0,syndex_data + 2*3 ; Clear position of spot No3 ld fifo_trig,#HIGH_LEVEL ld filt_trig,#HIGH_LEVEL ld trig_max,#HIGH_LEVEL ei ; Enable all ITs ret ; +--------------------------------------------------------------------------+ ; | IT_START_LINE_ | ; | | ; | This is the start of line interrupt. | ; | INPUTS: Nothing. | ; | OUTPUTS: Nothing. | ; +--------------------------------------------------------------------------+ it_start_line_: ;pusha ; The "pusha" is made by the monitor ; Enable Serial IT during it_start_line ; ------------------------------------- di orb int_mask,#40h ; Enable Serial RX/TX IT ei ; Change state of flash ; --------------------- xorb port1,#LED1 ; Inverse flash ; Update CAM HSO ; -------------- ldb hso_comm,#050h ; One CAM HSO to clear HSO.0 ld hso_time,tper ; each TPER_TYP and a start of line IT ldb hso_comm,#04Eh ; One CAM HSO to reset timer 2 ld hso_time,tper ; ** Test for exposure command to do ** jbs flags,EXPO_ALREADY_MADE,it_start_cont_ ldb hso_comm,#60h ld hso_time,expo_no it_start_cont_: andb flags,#(0FFh-(1 SHL EXPO_ALREADY_MADE)) ; Read FIFO and follow target ; --------------------------- jbs flags,INIT_PHASE,it_nul_ it_start_fifo_: START_MEASURE scall rd_fifo_ ;SONDE nb_spots,sd_nb_spots ld fifo_trig,smin call detect_spots_ SONDE smin,sd_trig_level END_MEASURE it_ax SONDE it_ax,sd_time_it ; End of interrupt ; ---------------- it_nul_: popa ret ; +--------------------------------------------------------------------------+ ; | IT_END_LINE_ | ; | | ; | This is the end of line interrupt. | ; | INPUTS: Nothing. | ; | OUTPUTS: Nothing. | ; +--------------------------------------------------------------------------+ it_end_line_: ;pusha ; The "pusha" is made by the monitor ; Read max from CCD ; ----------------- ld max_ccd,MOCO ; Read Maximum gray scale of the CCD and max_ccd,#0FFFh ; Scheduler for end of line ; ------------------------- br [it_end_jmp] ; Zero control at beginning ; ------------------------- it_zero_: cmp num_linelo,#NB_VPR_LINES jlt it_zero_cont_ ld it_end_jmp,#it_expo_init_ it_zero_cont_: ld it_ax,#16 ; Command for a black line st it_ax,COMA ; to average the background ldb it_axlo,#80h ; Reset Fifo stb it_axlo,FIFO sjmp it_end_line_end_ ; Exposure control init ; --------------------- it_expo_init_: dec expo_count ; Decrement number of exposure periods jne it_expo_cont_init_ ; Count is NULL ? --> No continue ld it_end_jmp,#it_expo_ ; Next function is normal expo ld smin,#0F00h/2 andb flags,#(0FFh-(1 SHL INIT_PHASE)); Init phase flag is finished it_expo_cont_init_: scall expo_control_ ; Call expo control routine ldb it_axlo,#80h ; Reset Fifo stb it_axlo,FIFO sjmp it_end_line_end_ ; Exposure control ; ---------------- it_expo_: dec expo_count ; Decrement number of exposure periods jne it_expo_cont_ ; Count is NULL ? --> No continue jbs flags,MAXDIF_MEASURE,it_maxdif_ orb flags,#(0FFh-(1 SHL MAXDIF_MEASURE)) ld it_ax,#9 ; We want to measure differential max st it_ax,MOCO sjmp it_end_line_end_ it_maxdif_: ld trig_max,max_ccd andb flags,#(0FFh-(1 SHL MAXDIF_MEASURE)) ld it_ax,#1 st it_ax,MOCO ld expo_jmp,#expo_get_max_ ; Restore expo control ld expo_count,#NB_EXPOS sjmp it_end_line_end_ it_expo_cont_: scall expo_control_ ; Call expo control routine sjmp it_end_line_end_ ; End of interrupt ; ---------------- it_end_line_end_: ; ** Update Trigger level ** st smin,LIM1 ; Loading of trigger level registers st smax,LIM2 ; ** Update counters ** inc zero_count ; Increment counter for zero control add num_linelo,#1 ; Increment number of line addc num_linehi,0 ; ** Launch yes|no a exposure command ** cmp expo_no,timer2 ; Exposure time is bigger than timer 2 ? jh it_end_line_quit_ ; Yes --> it_end_line_quit_ ldb hso_comm,#60h ; Load CAM for next exposure line ld hso_time,expo_no orb flags,#(1 SHL EXPO_ALREADY_MADE) ; ** Bye, Bye ** it_end_line_quit_: popa ret ; +--------------------------------------------------------------------------+ ; | EXPO_CONTROL_ | ; | | ; | This routine controls the exposure time of the CCD. | ; | INPUTS: max_ccd = Maximum of (n-2) line. | ; | expo_lum = Maximum of (n-1) line. | ; | OUTPUTS: expo = Exposure time of next line. | ; | expo_no = No exposure time of next line. | ; +--------------------------------------------------------------------------+ expo_control_: ; Expo scheduler ; -------------- br [expo_jmp] ; We just do a measure ; -------------------- expo_get_max_: ld expo_jmp,#expo_change_ ; Next time, we change exposure time ld expo_lum,max_ccd ; Store max_cdd in expo_lum ld tper,#TPER_TYP ; And next line is normal ld expo_no,tper sub expo_no,expo ret ; We do nothing ; ------------- expo_wait_: ld expo_jmp,#expo_get_max_ ; Next time, we just do a measure ld tper,#TPER_TYP ; And next line is normal ld expo_no,tper sub expo_no,expo ret ; Update exposure time ; -------------------- ; ** Keep maximum of two lines ** expo_change_: ld expo_jmp,#expo_wait_ ; Next time, we do nothing cmp expo_lum,max_ccd jge expo_update_ ld expo_lum,max_ccd ; expo_lum=Max of two lines ; ** Store for transmit ** expo_update_: SONDE expo_lum,sd_expo_lum SONDE expo,sd_expo_time ; ** Test if last exposure is good ** cmp expo_lum,#EXPO_OK+EXPO_DT jgt expo_calc_ cmp expo_lum,#EXPO_OK-EXPO_DT jge expo_end_ ; ** Reajust exposure time because light is not good ** expo_calc_: clr it_d0hi ; it_d0=(EXPO_OK*expo(n-1))/Max(n-1) ld it_d0lo,expo mulu it_d0,#EXPO_OK divu it_d0,expo_lum jv expo_overflow_ ld expo,it_d0lo ; New expo=it_d0 (by default) ; ** Place threshold on exposure ** cmp it_d0lo,#EXPO_MIN ; if (new expoEXPO_MAX) jnh expo_end_ ; than new expo=EXPO_MAX expo_overflow_: ld expo,#EXPO_MAX ; End of exposure control ; ----------------------- expo_end_: ld tper,#TPER_TYP ; Next line is normal ld expo_no,tper ; but there is a new exposure time sub expo_no,expo ret ; +--------------------------------------------------------------------------+ ; | RD_FIFO_ | ; | | ; | This routine read the fifo memory to extract information. | ; | INPUTS: Nothing. | ; | OUTPUTS: Nothing. | ; +--------------------------------------------------------------------------+ ; /-(G)-\ (A): Grayscale before level in it_ax & sp_grb2 ; / \ (B): Grayscale after level in it_bx & sp_gra1 ; | | (C): Pixel number at level in it_cx & sp_pos2 ; | | (D): Pixel number at level in it_dx & sp_pos1 ; (B) (A) (E): Grayscale after level in it_ex & sp_gra2 ; | | (F): Grayscale before level in it_fx & sp_gra1 ;----(D)-----(C)----- (G): Maximum grayscale in it_gx & sp_maxi ; | | ; (F) (E) ; | | rd_fifo_: ; First tests on FIFO ; ------------------- ldb it_axlo,FIFO+1 ; Read FIFO status jbs it_axlo,FIFO_EMPTY,rd_fifo_quit_; FIFO empty ? --> Go out jbs it_axlo,FIFO_MIDLE,rd_fifo_err_ ; FIFO half full ? --> Yes --> Destroy it jbs it_axlo,FIFO_FULL,rd_fifo_err_ ; FIFO full ? --> Yes --> Destroy it ; Init variables ; -------------- clr it_fx ; Clear it_fx to mark starting of reading fifo clr sp_maxi ; Clear sp_maxi for the same reason clr nb_spots ; Clear nb spots detected ld it_d1lo,#fifo_data ; Init it_d1lo to fifo_data pointer ; Reading FIFO loop ; ----------------- ; ** Test FIFO without dead lock ** rd_fifo_loop_: cmpb nb_spots+1,#2*NB_MAX_SPOTS ; There are too many true spots ? jgt rd_fifo_err_ ; Yes --> Destroy FIFO cmpb nb_spots,#NB_MAX_SPOTS ; There are too many union spots ? jgt rd_fifo_err_ ; Yes --> Destroy FIFO ldb it_axlo,FIFO+1 ; The FIFO is empty ? jbs it_axlo,FIFO_EMPTY,rd_fifo_end_ ; Yes --> Go out without dead locking ld it_ax,FIFO ; Is it the first byte of datas ? jbc it_axhi,FIFO_BYTE,rd_fifo_loop_ ; No --> We search it --> rd_fifo_loop_ ldb it_axhi,FIFO jbc it_axhi,FIFO_END,rd_fifo_clean_ ; End of datas ? Yes --> rd_fifo_clean_ jbs it_axhi,FIFO_UP,rd_fifo_up_ ; Trigger by top --> rd_fifo_up_ sjmp rd_fifo_down_ ; Read the last bytes in the FIFO ; ------------------------------- rd_fifo_clean_: ldb 0,FIFO ; Remove 3 bytes in FIFO ldb 0,FIFO ldb 0,FIFO rd_fifo_end_: clr it_fx ; Clear it_fx to mark end of reading FIFO cmp sp_maxi,0 ; There is a last spot to store in memory ? bne rd_fifo_next_ ; Yes --> rd_fifo_next_ rd_fifo_quit_: ret ; The FIFO is bugged ! I destroy it ! ; ----------------------------------- rd_fifo_err_: ldb it_axlo,#80h ; Clear fifo stb it_axlo,FIFO clr nb_spots ret ; Clean FIFO for next spot ; ------------------------ rd_fifo_next_loop_1_: clr it_fx ldb 0,FIFO ldb 0,FIFO rd_fifo_next_loop_2_: ldb 0,FIFO ldb 0,FIFO ldb 0,FIFO ldb 0,FIFO ldb 0,FIFO ldb 0,FIFO sjmp rd_fifo_loop_ ; Reading a high transition ; ------------------------- rd_fifo_up_: ; ** Read gray scales and position ** and it_fx,it_ax,#0FFFh ; Gray scale before level in it_fx ldb it_bxlo,FIFO ; Read LSB gray scale after level ldb it_bxhi,FIFO ; Read MSB gray scale & MSB Pixel number ldb it_dxlo,FIFO ; Read LSB Pixel number ldb it_dxhi,it_bxhi andb it_bxhi,#0Fh ; Gray scale after level in it_bx shrb it_dxhi,#4 andb it_dxhi,#7h ; Pixel number in it_dx ; ** Test if high transition is in window ** cmp it_dx,win_start jlt rd_fifo_next_loop_1_ cmp it_dx,win_end jgt rd_fifo_next_loop_1_ sjmp rd_fifo_loop_ ; Reading a low transition ; ------------------------ rd_fifo_down_: cmp it_fx,0 ; If there is a first low transition je rd_fifo_next_loop_2_ ; then we ignore it and jump to next ; ** Read gray scales and position ** andb it_axhi,#0Fh ; Gray scale before level in it_ax ldb it_exlo,FIFO ; Read LSB gray scale after level ldb it_exhi,FIFO ; Read MSB gray scale & MSB Pixel number ldb it_cxlo,FIFO ; Read LSB Pixel number ldb it_cxhi,it_exhi andb it_exhi,#0Fh ; Gray scale after level in it_ex shrb it_cxhi,#4 ; Pixel number in it_cx ; ** Read maximum gray scale of the spot ** ldb it_gxlo,FIFO ; Read LSB gray scale at maximum ldb it_gxhi,FIFO ; Read MSB gray scale & MSB pixel number ldb 0,FIFO ; Read LSB pixel number at maximum andb it_gxhi,#0Fh ; Maximum gray scale in it_gx jbc it_cxhi,3,rd_fifo_parasit_ ; Sign bit is stored in MSB bit of orb it_gxhi,#80h ; maximum gray scale ; ** Detect if this is a parasit spot ** rd_fifo_parasit_: andb it_cxhi,#7h ; Clear Sign bit sub it_d0lo,it_cx,it_dx ; it_d0lo is the width of a spot cmp it_d0lo,#WIDTH_PARASIT_SPOT ; This is a parasit ? jgt rd_fifo_un_ ; Yes --> rd_fifo_loop_ clr it_fx sjmp rd_fifo_loop_ ; Union of spots ; -------------- rd_fifo_un_: incb nb_spots+1 ; Increment number of true spots cmp sp_maxi,0 ; There are two spots for an union ? jne rd_fifo_union_ ; Yes --> rd_fifo_union_ ; ** First union ** ld sp_grb1,it_fx ld sp_pos1,it_dx ld sp_gra1,it_bx ld sp_grb2,it_ax ld sp_pos2,it_cx ld sp_gra2,it_ex ld sp_maxi,it_gx sjmp rd_fifo_loop_ ; ** Others unions ** rd_fifo_union_: ldb it_d0lo,sp_maxi+1 ; Make of xor between sign bit of two spots xorb it_d0lo,it_gxhi ; to known if the sign bits are the same jbs it_d0lo,7,rd_fifo_next_ ; It's not the same --> No union --> rd_fifo_next_ ; sub it_d0lo,it_cx,sp_pos1 ; <-------A-------> shr it_d0lo,#1 ; | | cmp it_d0lo,#EPSILON_MIN ; | <-B-> | jgt rd_fifo_epsmin_ ; | _ | | _ | ld it_d0lo,#EPSILON_MIN ; | / \ | | / \ | rd_fifo_epsmin_: ; |/ \| |/ \| cmp it_d0lo,#EPSILON_MAX ; / 1 \___/ 2 \ jlt rd_fifo_epsmax_ ; / \ ld it_d0lo,#EPSILON_MAX ; rd_fifo_epsmax_: ; The way of union of two spots is : sub it_d0hi,it_dx,sp_pos2 ; if B>(A/2) there is no union else cmp it_d0hi,it_d0lo ; there is union of the two spots jgt rd_fifo_next_ ; ** Union of two spots ** ld sp_grb2,it_ax ; When a union is made, we keep ld sp_pos2,it_cx ; the maximum gray scale of the two spots ld sp_gra2,it_ex cmp sp_maxi,it_gx bh rd_fifo_loop_ ld sp_maxi,it_gx sjmp rd_fifo_loop_ ; Store datas for a new spot ; -------------------------- rd_fifo_next_: ; ** Adjust pixel number of / level ** clr it_d0hi sub it_d0lo,sp_gra1,fifo_trig shl it_d0lo,#3 sub it_d1hi,sp_gra1,sp_grb1 divu it_d0,it_d1hi shl sp_pos1,#3 sub sp_pos1,it_d0lo ; ** Adjust pixel number of \ level ** clr it_d0hi sub it_d0lo,fifo_trig,sp_gra2 shl it_d0lo,#3 sub it_d1hi,sp_grb2,sp_gra2 divu it_d0,it_d1hi shl sp_pos2,#3 sub sp_pos2,it_d0lo ; ** Increment number of spots and store ** incb nb_spots ; Increment number of spots add sp_pos1,sp_pos2 ; Sum pixels number st sp_pos1,[it_d1lo]+ ; Store sum of pixels nb st sp_maxi,[it_d1lo]+ ; Store maximum gray scale cmp it_fx,0 be rd_fifo_quit_ ld sp_grb1,it_fx ; Load new spot in old spot ld sp_pos1,it_dx ld sp_gra1,it_bx ld sp_grb2,it_ax ld sp_pos2,it_cx ld sp_gra2,it_ex ld sp_maxi,it_gx sjmp rd_fifo_loop_ ; +--------------------------------------------------------------------------+ ; | DETECT_SPOTS_ | ; | | ; | This routine detects and follows the target. | ; | INPUTS: nb_spots = Number of spots. | ; | fifo_data = Buffer of spots datas. | ; | OUTPUTS: nb_spots = Number of spots followed. | ; | spots_data = Buffer of good spots. | ; +--------------------------------------------------------------------------+ detect_spots_: ; Count number of spots ; --------------------- cmpb nb_spots,#2 ; There are 2 spots ? blt detect_lose_ ; No --> detect_lose_ cmp nb_founds,#NB_MIN_FOUNDS ; I have seen a few good targets ? bne detect_found_ ; No --> detect_found_ ; Following target phase ; ---------------------- ; ** Follow the target if there are too many spots ** scall follow_target_ ; Windowing for each spot cmpb nb_spots,#2 ; Nb spots follows is good ? bne detect_lose_ ; No --> detect_lose_ SONDE nb_spots,sd_nb_spots ld it_d0lo,#spots_data ; Interpret target scall semantic_target_ ; This a true target ? bbc it_axlo,0,detect_lose_ ; No --> detect_lose_ ; ** Update Windows ** ;ld win_start,spots_data+4*0 ; The window is defined ;ld win_end, spots_data+4*4 ; by the position of the 1st ;shr win_start,#4 ; Divide by 16 to have a true pixel ;shr win_end,#4 ; Divide by 16 to have a true pixel ;sub win_start,#WINDOW_MARGE ; and the last spot with ;add win_end,#WINDOW_MARGE ; a little marge ; ** Update trigger levels ** detect_seuil_: ;mulu it_d0,max_spots,#5 ;shr it_d0lo,#3 ;mulu it_d1,filt_trig,#5 ;add it_d1lo,it_d0lo ;ld filt_trig,it_d1lo ;ld smin,it_d1lo ;ld smax,it_d1lo ; ** Store for Syndex transmit ** detect_store_: clrb nb_spots+1 st nb_spots,syndex_data ld it_ax,spots_data + 4*0 ; Store position of spot No1 st it_ax,syndex_data + 2*1 ld it_ax,spots_data + 4*1 ; Store position of spot No2 st it_ax,syndex_data + 2*2 ld it_ax,spots_data + 4*2 ; Store position of spot No3 st it_ax,syndex_data + 2*3 ; ** End of detect spots ** detect_found_end_: ret ; Detect target phase ; ------------------- detect_found_: cmpb nb_spots,#2 ; We have 2 good spots ? jne detect_found_end_ ; No --> detect_found_end_ ld it_d0lo,#fifo_data ; Semantic target scall semantic_target_ ; This is a good target ? jbc it_axlo,0,detect_found_end_ ; No --> detect_found_end_ inc nb_founds ; Increment nb founds targets cmp nb_founds,#NB_MIN_FOUNDS ; I have seen a few good targets ? jne detect_found_end_ ; No --> detect_found_end_ ld d0lo,#fifo_data ; Block move to spots datas ld d0hi,#spots_data ; when the target is good ld ax,#6 bmovi d0,ax ret ; Losing target phase ; ------------------- ; ** The target is abnormal ** detect_lose_: cmp nb_founds,0 ; The target is very losed ? je detect_target_lose_ ; Yes --> detect_target_lose_ dec nb_founds ; Decrement nb founds targets ret ; ** The target is very losed ** detect_target_lose_: clr win_start ; Initialize window ld win_end,#NB_PIXELS sub smin,#STEP_LEVEL ; Decrement trigger level cmp smin,#LOW_LEVEL ; We reach a low level ? jge detect_target_lose_clean_ ; No --> continue ld smin,trig_max ; Yes --> Restart level to differential maximum shr smin,#1 cmp smin,#LOW_LEVEL jge detect_target_lose_clean_ ld smin,#LOW_LEVEL detect_target_lose_clean_: ld smax,smin ; Change the max level too ld filt_trig,smin ; filt_trig follows the trigger st 0,syndex_data + 2*0 ; Clear number of spots st 0,syndex_data + 2*1 ; Clear position of spot No1 st 0,syndex_data + 2*2 ; Clear position of spot No2 st 0,syndex_data + 2*3 ; Clear position of spot No3 ret ; +--------------------------------------------------------------------------+ ; | FOLLOW_TARGET_ | ; | | ; | This routine make union of new spots and old spots. | ; | INPUTS: spots_data = Buffer of following spots. | ; | fifo_data = Buffer of new spots. | ; | OUTPUTS: nb_spots = Number of spots which are good. | ; | spots_data = Buffer of new following spots. | ; +--------------------------------------------------------------------------+ follow_target_: ; Initialize Phase ; ---------------- ldb it_axlo,nb_spots ; Initialize counter of loop with spot number ldb it_exlo,#5 ; Initialize number of window clrb it_axhi ; Clearflag clrb nb_spots ; Clear number of spots followed ld max_spots,#0FFFh ; Initialize minimum gray scale of spots ld it_d0lo,#spots_data-4 ; Initialize pointers ld it_d0hi,#fifo_data ; Take a new window ; ----------------- follow_target_loop1_: jbc it_axhi,0,follow_target_no_spot_; There is spot in last window ? incb nb_spots ; Yes, so increase number of spots follow_target_no_spot_: add it_d0lo,#4 ; Increment pointer to next window decb it_exlo ; Decrement number of windows to do jlt follow_target_end_ ; It is finish ? Yes --> follow_target_end_ ldb it_axhi,0 ; Clear flag ld it_bx,[it_d0lo] ; Load spot position in it_bx ld it_cx,it_bx sub it_bx,#SPOT_MARGE*2*8 ; it_bx is for left side window add it_cx,#SPOT_MARGE*2*8 ; it_cx is for right side window ; Take a new spot with the current window ; --------------------------------------- follow_target_loop2_: ld it_dx,[it_d0hi] ; New spot is in window ? cmp it_dx,it_bx ; Is it before / window ? jlt follow_target_next_ ; Yes --> Ignore it and go to next cmp it_dx,it_cx ; Is it after \ window ? jgt follow_target_loop1_ ; Yes --> Pass to next spot window ldb it_exhi,3[it_d0lo] ; Test Sign bits of two spots xorb it_exhi,3[it_d0hi] ; The signs are different ? jbc it_exhi,7,follow_target_next_ ; No, so pass to next --> follow_target_next_ add it_dx,[it_d0lo] ; The spot is in window, so sum shr it_dx,#1 ; the two spots to increase precision ; Store spot which is in window ; ----------------------------- follow_target_store_: ldb it_axhi,#1 ; Set flag st it_dx,[it_d0lo] ; Store spot position ld it_d1lo,2[it_d0hi] ; Read maximum of spot st it_d1lo,2[it_d0lo] ; Store maximum of spot with sign andb it_d1lo+1,#07Fh ; Clear Sign bit cmp max_spots,it_d1lo ; Keep minimum gray scale of good spots jle follow_target_next_ ld max_spots,it_d1lo ; Loop while there are spots ; -------------------------- follow_target_next_: add it_d0hi,#4 ; Pass to next new spot djnz it_axlo,follow_target_loop2_ ; Loop while there are spots jbc it_axhi,0,follow_target_end_ ; There is spot in last window ? incb nb_spots ; Yes, so increase number of spots follow_target_end_: ret ; +--------------------------------------------------------------------------+ ; | SEMANTIC_TARGET_ | ; | | ; | This routine interpret the target and say if this is a good target. | ; | INPUTS: it_d0lo = Buffer of spots. | ; | OUTPUTS: it_axlo = Boolean which is true(1) if this is a good target. | ; +--------------------------------------------------------------------------+ semantic_target_: ldb it_axlo,#1 ret ; Test target pattern ; ------------------- clr it_ax ldb it_axlo,4*0+3[it_d0lo] ; Load Sign bit of first spot xorb it_axlo,4*4+3[it_d0lo] ; Xor bit with the last spot jbs it_axlo,7,semantic_target_false_; If they have the same sign, this is ok ! ldb it_axlo,4*1+3[it_d0lo] ; Take Sign bit of the three central spots andb it_axlo,4*2+3[it_d0lo] ; and make a logical AND andb it_axlo,4*3+3[it_d0lo] ; If they have the same sign, AND is one ! ldb it_bxlo,4*1+3[it_d0lo] ; Take Sign bit of the three central spots orb it_bxlo,4*2+3[it_d0lo] ; and make a logical OR following by a NOT orb it_bxlo,4*3+3[it_d0lo] ; If they have the same sign, OR-NOT is one ! notb it_bxlo orb it_axlo,it_bxlo jbc it_axlo,7,semantic_target_false_ ; The is not a target ; ------------------- semantic_target_false_: clrb it_axlo ; Clear flag to say it is not a good target ret ; +--------------------------------------------------------------------------+ ; | IT_COM_ | ; | | ; | This is the rs232 interrupt routine. | ; | INPUTS: Nothing. | ; | OUTPUTS: Nothing. | ; +--------------------------------------------------------------------------+ it_com_: ;pusha ; The "pusha" is made by the monitor ; Read Serial Status register ; --------------------------- ldb com_state+1,sp_stat jbs com_state+1,5,it_com_start_ jbc com_state+1,6,it_com_end_ ; Jump to right state ; ------------------- it_com_start_: jbs com_state,RS_RTR_SENT,it_com_rtr_sent_ jbs com_state,RS_RECEIVE,it_com_receive_ jbs com_state,RS_TRANSMIT,it_com_send_ jbs com_state,RS_WAIT_RTR,it_com_wait_rtr_ jbs com_state,RS_SLEEP,it_com_sleep_ it_com_end_: popa ret ; We send a RTR to receive ; ------------------------ it_com_rtr_sent_: ldb com_state,#(1 SHL RS_RECEIVE) popa ret ; We receive some datas ; --------------------- it_com_receive_: stb sbufrx,[com_dma_addr]+ dec com_dma_size jne it_com_end_ ldb com_state,#(1 SHL RS_SLEEP) push #it_com_end_ br [com_dma_iptr] ; We receive a RTR while we sleep ; ------------------------------- it_com_sleep_: ldb 0,sbufrx ldb com_state,#(1 SHL RS_RTR_RECEIVED) popa ret ; We wait a RTR and now we transmit ; --------------------------------- it_com_wait_rtr_: ldb 0,sbufrx ldb com_state,#(1 SHL RS_TRANSMIT) ; We transmit some datas ; ---------------------- it_com_send_: cmp com_dma_size,0 je it_com_send_end_ dec com_dma_size ldb sbuftx,[com_dma_addr]+ popa ret it_com_send_end_: ldb com_state,#(1 SHL RS_SLEEP) push #it_com_end_ br [com_dma_iptr] ; +--------------------------------------------------------------------------+ ; | COM_I_SHARED_ | ; | | ; | This routine inits a data reception. | ; | INPUTS: com_dma_size = Number of bytes to transfer. | ; | com_dma_addr = Buffer Soft-DMA address. | ; | OUTPUTS: Nothing. | ; +--------------------------------------------------------------------------+ com_i_shared_: ; Save context and Soft-DMA ; ------------------------- pop com_dma_iptr ; Save IPTR for communication thread ; Send RTR to signal we are ready to receive ; ------------------------------------------ ldb com_state,#(1 SHL RS_RTR_SENT) ldb sbuftx,0 ; Send RTR=0 ret ; Switch to calcul thread ; +--------------------------------------------------------------------------+ ; | COM_O_SHARED_ | ; | | ; | This routine inits a data transmission. | ; | INPUTS: com_dma_size = Number of bytes to transfer. | ; | com_dma_addr = Buffer Soft-DMA address. | ; | OUTPUTS: Nothing. | ; +--------------------------------------------------------------------------+ com_o_shared_: ; Save context ; ------------ pop com_dma_iptr ; Save IPTR for communication thread ; Test if we already received a RTR ; --------------------------------- orb com_state,#(1 SHL RS_WAIT_RTR) jbc com_state,RS_RTR_RECEIVED,com_wait_rtr_ ; We send a first char to run a transmit sequence ; ----------------------------------------------- com_o_frame_: ldb com_state,#(1 SHL RS_TRANSMIT) dec com_dma_size ldb sbuftx,[com_dma_addr]+ ; Send first char com_wait_rtr_: ret ; Switch to calcul thread'') dnl +------------------------------------------------------------------------+ dnl | Declaration of the allocate memories macros | dnl +------------------------------------------------------------------------+ dnl -------------------------------- Allocate -------------------------------- dnl logical_(label,items) ; Allocate items bytes define(`logical_', `divert(DIVUNI) $1 : dsl eval(($2+3)>>2) divert dnl') dnl integer_(label,items) ; Allocate items 32bits integers define(`integer_', `divert(DIVUNI) $1 : dsl $2 divert dnl') dnl +------------------------------------------------------------------------+ dnl | Declaration of initializing macros | dnl +------------------------------------------------------------------------+ define(`true',`1') define(`false',`0') define(`data_ini_end',`dnl divert(DIVINI)` dcw 0'divert`'dnl') dnl cell_ini_({repeat[,step]}) define(`cell_ini_',`dnl divert(DIVINI)dnl ifelse($1,,`dcw 0 ',`dcw $1,eval(cell_size_*ifelse($2,,1,$2)) cell_ini_(shift(shift($@)))') divert`'dnl') dnl logical_ini_(value,label,offset,repeat,step,...) define(`logical_ini_',`pushdef(`cell_size_',1) dnl divert(DIVINI) dcw $2`'ifelse($#,2,,$3,0,,+$3) ;dcw log_ini_ dcw $1 cell_ini_(shift(shift(shift($@)))) dnl divert`'popdef(`cell_size_')dnl') dnl integer_ini_(value,label,offset,repeat,step,...) define(`integer_ini_',`pushdef(`cell_size_',4) dnl divert(DIVINI) dcw $2`'ifelse($#,2,,$3,0,,+$3*4) dcw int_ini_ dcw $1 cell_ini_(shift(shift(shift($@)))) dnl divert`'popdef(`cell_size_')dnl') dnl +------------------------------------------------------------------------+ dnl | Declaration of copy macros | dnl +------------------------------------------------------------------------+ dnl logical_copy_(dstlabel,srclabel,items) def(`logical_copy_',`ifelse(eval($3),1,`dnl mov al,BYTE PTR $2 mov BYTE PTR $1,al',eval($3),2,`dnl mov ax,WORD PTR $2 mov WORD PTR $1,ax',`dnl cld mov esi,OFFSET $2 mov edi,OFFSET $1 mov ecx,$3 rep movsb')') dnl cell_copy_(dstlabel,srclabel,items) define(`cell_copy_',`ifelse(eval($3),1,`dnl mov eax,DWORD PTR $2 mov DWORD PTR $1,eax',`dnl cld mov esi,OFFSET $2 mov edi,OFFSET $1 mov ecx,$3 rep movsd')') dnl integer_copy_(dstlabel,srclabel,items) def(`integer_copy_',`cell_copy_($@)') dnl +------------------------------------------------------------------------+ dnl | Declaration of sequencing macros | dnl +------------------------------------------------------------------------+ dnl pushlabel(label) define(`labelnumber',0) define(`pushlabel',`pushdef(`$1',`$1_'labelnumber`_')dnl define(`labelnumber',incr(labelnumber))')dnl define(`poplabel',`popdef(`$1')')dnl dnl if_(log) def(`if_', `pushlabel(`forwd') cmpb 0,$1 be forwd') dnl ifnot_(log) def(`ifnot_', `pushlabel(`forwd') cmpb 0,$1 bne forwd') dnl else_() def(`else_',`pushdef(`swap',forwd)poplabel(`forwd')pushlabel(`forwd') br forwd swap: popdef(`swap')') dnl endif_() def(`endif_', ` forwd: poplabel(`forwd')') dnl while_() def(`while_',`pushlabel(`bakwd')pushlabel(`forwd')dnl br forwd bakwd:') dnl endwhile_(log) def(`endwhile_',`dnl forwd: cmpb 0,$1 bne bakwd poplabel(`forwd')poplabel(`bakwd')') dnl +------------------------------------------------------------------------+ dnl | Declaration of I/O macros | dnl +------------------------------------------------------------------------+ def(`FINFO_ini_') def(`FINFO_get_',`dnl ld ax,sd_expo_lum st ax,$1 ld ax,sd_expo_time st ax,$1+2 ld ax,sd_time_it st ax,$1+4 ld ax,sd_nb_spots st ax,$1+6 ld ax,sd_trig_level st ax,$1+8') def(`FINFO_end_') def(`FPICS_ini_') def(`FPICS_get_',`dnl andb int_mask,#0F7h ; Disable Start of line interrupt ld d0lo,#syndex_data ; Block move to user datas ld d0hi,#$1 ld ax,#4 bmovi d0,ax orb int_mask,#08h ; Enable Start of line interrupt') def(`FPICS_end_') dnl +------------------------------------------------------------------------+ dnl | Declaration of communications macros | dnl +------------------------------------------------------------------------+ dnl thread_(linkNumber) def(`thread_',`dnl `; +--------------------------------------------------------------------------+ ; | COMMUNICATION THREAD | ; | | ; | This routine is used to communicate with external processors. | ; | INPUTS: Nothing. | ; | OUTPUTS: Nothing. | ; +--------------------------------------------------------------------------+ com$1_thread_: 'dnl') dnl PPL_i_logical(linkNumber,nb_items,buffer) def(`PPL_i_logical',`dnl ld com_dma_size,`#'$2 ; com_dma_size=Number of bytes to receive ld com_dma_addr,`#'$3 ; com_dma_addr=Buffer address lcall com_i_shared_') dnl PPL_o_logical(linkNumber,nb_items,buffer) def(`PPL_o_logical',`dnl ld com_dma_size,`#'$2 ; com_dma_size=Number of bytes to send ld com_dma_addr,`#'$3 ; com_dma_addr=Buffer address lcall com_o_shared_') dnl PPL_i_integer(linkNumber,nb_items,buffer) def(`PPL_i_integer',`PPL_i_logical($1,eval($2*4),$3)') dnl PPL_o_integer(linkNumber,nb_items,buffer) def(`PPL_o_integer',`PPL_o_logical($1,eval($2*4),$3)') dnl PPL_ini_(linkNumber) define(`PPL_ini_',`dnl `; Synchronization PPL_o_logical ; ----------------------------- ld com_dma_size,#1 ; com_dma_size=Number of bytes to send ld com_dma_addr,#synchro ; com_dma_addr=Buffer address lcall com_o_shared_ stb 0,synchro '') dnl PPL_end_(linkNumber) define(`PPL_end_') dnl spawn_(linkNumber) def(`spawn_', `dnl lcall com$1_thread_ ; Run communication thread spawn_wait_: cmpb 0,synchro jne spawn_wait_') dnl +------------------------------------------------------------------------+ dnl | Declaration of synchronization macros | dnl +------------------------------------------------------------------------+ dnl semaphores_(n) define(`semaphores_',`dnl') dnl Pre0_(s) def(`Pre0_',`dnl orb sem+eval($1/8),`#0'eval(2**($1%8),16)h ; Set semaphore $1') dnl Suc0_(`s') def(`Suc0_',`pushlabel(`lsuc0')dnl lsuc0: jbc sem+eval($1/8),eval($1%8),lsuc0 ; Test semaphore $1 and we wait a `Pre0_($1)' poplabel(`lsuc0') andb sem+eval($1/8),`#0FFh-0'eval(2**($1%8),16)h ; Reset semaphore $1') dnl Pre1_(s) def(`Pre1_',`dnl lcall suc_$1_ ; Switch to `Suc_'$1_') dnl Suc1_(s) def(`Suc1_',`pushlabel(`lsuc1')dnl suc_$1_: xorb sem+eval($1/8),`#0'eval(2**($1%8),16)h ; Complements semaphore $1 jbc sem+eval($1/8),eval($1%8),lsuc1 ; If semaphore is 0 (Pass 2), continue ret ; else return sub-routine (Pass 1) lsuc1: poplabel(`lsuc1')') dnl +------------------------------------------------------------------------+ dnl | Declaration of main macros | dnl +------------------------------------------------------------------------+ dnl main_ini_() def(`main_ini_',`dnl ; +--------------------------------------------------------------------------+ ; | MAIN PROGRAM | ; | | ; | This routine is the main program. | ; | INPUTS: Nothing. | ; | OUTPUTS: Nothing. | ; +--------------------------------------------------------------------------+ main_: ldb axlo,`#'1 stb axlo,_IOok_ lcall prog_ini_ ; Init program') dnl main_end_() def(`main_end_',`dnl sjmp $ ; Wait Reset') dnl end_() def(`end_',` ; Initialized datas ; ----------------- sd_expo_lum : dcw 0 sd_expo_time : dcw 0 sd_time_it : dcw 0 sd_nb_spots : dcw 0 sd_trig_level : dcw 0 synchro : dcb 1 undivert(DIVCST)dnl ; Initializing datas ; ------------------ undivert(DIVINI) ; Unitialized datas ; ----------------- DSEG at 0F000h fifo_data : dsw 2*NB_MAX_SPOTS spots_data : dsw 5*2 syndex_data : dsw 4 undivert(DIVUNI) end') dnl +------------------------------------------------------------------------+ dnl | Declaration of chronos macros | dnl +------------------------------------------------------------------------+ define(`tree_up_',`dnl'); define(`tree_dn_',`dnl'); define(`tree_dn_end',`dnl'); dnl +------------------------------------------------------------------------+ dnl | Declaration of ALU macros | dnl +------------------------------------------------------------------------+ dnl logNot(s1,dst) ; dst=not(s1) def(`logNot',`dnl ldb axlo,$1 notb axlo stb axlo,$2') dnl logAnd(s1,s2,dst) ; dst=s1&s2 def(`logAnd',`dnl ldb axlo,$1 andb axlo,$2 stb axlo,$3') dnl logOr(s1,s2,dst) ; dst=s1|s2 def(`logOr',`dnl ldb axlo,$1 orb axlo,$2 stb axlo,$3') dnl logXor(s1,s2,dst) ; dst=s1^s2 def(`logXor',`dnl ldb axlo,$1 xorb axlo,$2 stb axlo,$3') dnl intEqu(s1,s2,dst) ; dst=(s1==s2) def(`intEqu',`pushlabel(`lintequ')dnl ld ax,$1 cmp ax,$2 ldb axlo,`#'1 je lintequ decb axlo lintequ: poplabel(`lintequ') stb axlo,$3') dnl intNeq(s1,s2,dst) ; dst=(s1!=s2) def(`intNeq',`pushlabel(`lintneq')dnl ld ax,$1 cmp ax,$2 ldb axlo,`#'1 jne lintneq decb axlo lintneq: poplabel(`lintneq') stb axlo,$3') dnl intGeq(s1,s2,dst) ; dst=s1>=s2 def(`intGeq',`pushlabel(`lintgeq')dnl ld ax,$1 cmp ax,$2 ldb axlo,`#'1 jge lintgeq decb axlo lintgeq: poplabel(`lintgeq') stb axlo,$3') dnl intNge(s1,s2,dst) ; dst=s1