with COMMON_TO_BOTH_488; use COMMON_TO_BOTH_488; with HW_SPECIFIC_CONTROLLER_488; use HW_SPECIFIC_CONTROLLER_488; with HW_SPECIFIC_EVENT_488; use HW_SPECIFIC_EVENT_488; with CONVERSIONS; use CONVERSIONS; with UNCHECKED_CONVERSION; with UNCHECKED_DEALLOCATION; with CALENDAR; use CALENDAR; with UATL_OPCOM; use UATL_OPCOM; with PC_HW_488; use PC_HW_488; package body CONTROLLER_488 is task body CONTROLLER_488_TASK is SP_TALK_BUFFER : SP_SERVICE_ARRAY; SP_TALK_LENGTH : INTEGER_16; TERMINAL_TALKER : ID_TYPE; COMMANDS : SMALL_MESSAGE; RCV_PTR : MESSAGE_POINTER; SP_COUNT : DATA_BYTE_COUNT_TYPE; SP_INFO : SERIAL_POLL_RECORD; TERMINAL_STATUS_REGISTER : DATA_BYTE; STATUS : STATUS_TYPE; TX_STATUS : STATUS_TYPE; TERMINATION : array (ID_TYPE'first..ID_TYPE'last) of TERMINATION_TYPE := (others => LF); THE_EVENT : PC_STATUS_TYPE; THE_SERVICE_MASK : INTEGER_16 := 0; procedure RECEIVE_MESSAGE(THE_TALKER : ID_TYPE; -- To record talker THE_STATUS : out STATUS_TYPE; WAIT_TIME : DURATION := 0.5) is --\ This procedure is called when the interface receives the command --\ ADDRESSED_AS_LISTENER from the interface bus. The procedure will --\ generate a new link in the RECEIVE_QUEUE, call a hardware specific --\ routine to get the message, and release the RECEIVE task so the --\ message can be sent to the user. COUNT : INTEGER_16; --Number of received bytes. STATUS : STATUS_TYPE; begin case TERMINATION(THE_TALKER) is when EOI => HW_RECEIVE_MESSAGE_EOI(COUNT, STATUS, WAIT_TIME); when LF => HW_RECEIVE_MESSAGE_LF(COUNT, STATUS, WAIT_TIME); when WC => null; end case; if STATUS = OK and COUNT > 0 then declare RECEIVED_MESSAGE : GENERAL_488_MESSAGE(COUNT); begin -- To record talker RECEIVED_MESSAGE.RECEIVE(THE_TALKER) := TRUE; RECEIVED_MESSAGE.MESSAGE := RECEIVED_MESSAGE_PTR.MESSAGE.MESSAGE(1..COUNT); RCV_PTR := new MESSAGE_LINK'(null, 0.0, RECEIVED_MESSAGE); QUEUE_TASK.QUEUE(RECEIVE_QUEUE, RCV_PTR); end; select IO_488.UNLOCK; else null; end select; end if; THE_STATUS := STATUS; end RECEIVE_MESSAGE; procedure SET_LISTENER(ID : ID_TYPE) is begin -- SET_LISTENER -- Send Listen address COMMANDS.LENGTH := 1; COMMANDS.DATA(1) := 32 + DATA_BYTE(ID); HW_SET_LISTENER(COMMANDS); end SET_LISTENER; procedure SET_LISTENER(IDS : INTERFACE_USERS) is begin -- SET_LISTENER COMMANDS.LENGTH := 1; for LISTENER in INTERFACE_USERS'range loop if IDS(LISTENER) then COMMANDS.DATA(COMMANDS.LENGTH) := 32 + DATA_BYTE(LISTENER); COMMANDS.LENGTH := COMMANDS.LENGTH + 1; end if; end loop; COMMANDS.LENGTH := COMMANDS.LENGTH - 1; HW_SET_LISTENER(COMMANDS); end SET_LISTENER; procedure SET_TALKER(ID : ID_TYPE) is begin -- SET_TALKER -- Send talker ID COMMANDS.LENGTH := 1; COMMANDS.DATA(1) := 64 + DATA_BYTE(ID); HW_SET_TALKER(COMMANDS); end SET_TALKER; procedure CLEAR_ALL_DEVICES is begin -- CLEAR_ALL_DEVICES HW_CLEAR_ALL_DEVICES; end CLEAR_ALL_DEVICES; procedure SERIAL_POLL is COUNT : INTEGER_16; --Number of received bytes. RESULTS : SMALL_ARRAY; RESULTS_COUNT : INTEGER_16; STATUS : STATUS_TYPE; begin -- SERIAL_POLL if ACTIVE_DEVICES /= null then HW_SERIAL_POLL (SP_TALK_BUFFER, SP_TALK_LENGTH, RESULTS, RESULTS_COUNT); SP_COUNT := 0; -- Number of serial polls processed and the index -- into the RELATED_INFO array pointing to the -- results of the serial poll. for DEV in ACTIVE_DEVICES'range loop -- The serial poll may terminate prematurely because there is -- an option that allows us to test the SRQ line before polling -- the next user in the list. This means that we will not -- receive a status of everyone on the setup-polling list. if ACTIVE_DEVICES(DEV).PROTOCOL = SRQ or ACTIVE_DEVICES(DEV).PROTOCOL = UATL then -- this user is in the polling list TERMINAL_STATUS_REGISTER := RESULTS(SP_COUNT); -- SP_INFO := SERIAL_POLL_CONVERT(TERMINAL_STATUS_REGISTER); -- if SP_INFO.REQUESTING_SERVICE then if (TERMINAL_STATUS_REGISTER/2**6) rem 2 = 1 then if ACTIVE_DEVICES(DEV).PROTOCOL = SRQ then declare RECEIVED_MESSAGE : GENERAL_488_MESSAGE(1); begin -- To record talker RECEIVED_MESSAGE .RECEIVE(ACTIVE_DEVICES(DEV).ADDRESS) := TRUE; RECEIVED_MESSAGE.MESSAGE(1) := TERMINAL_STATUS_REGISTER; RCV_PTR := new MESSAGE_LINK'(null, 0.0, RECEIVED_MESSAGE); QUEUE_TASK.QUEUE(RECEIVE_QUEUE, RCV_PTR); end; select IO_488.UNLOCK; else null; end select; elsif ACTIVE_DEVICES(DEV).PROTOCOL = UATL then TERMINAL_STATUS_REGISTER := TERMINAL_STATUS_REGISTER - 2**6; -- if SP_INFO.SERVICE > 0 then if TERMINAL_STATUS_REGISTER > 0 then -- for I in 1..SP_INFO.SERVICE loop for I in 1..TERMINAL_STATUS_REGISTER loop SET_LISTENER(DEVICE_ID); SET_TALKER(ACTIVE_DEVICES(DEV).ADDRESS); RECEIVE_MESSAGE(TERMINAL_TALKER, STATUS); UNTALK_UNLISTEN; end loop; else while POLL_QUEUE(ACTIVE_DEVICES(DEV).ADDRESS) .NEXT /= null loop SET_LISTENER(ACTIVE_DEVICES(DEV).ADDRESS); SET_TALKER(DEVICE_ID); HW_SEND(POLL_QUEUE(ACTIVE_DEVICES(DEV).ADDRESS) ,STATUS); if STATUS = OK then QUEUE_TASK.DEQUEUE (POLL_QUEUE(ACTIVE_DEVICES(DEV).ADDRESS)); end if; UNTALK_UNLISTEN; end loop; end if; end if; SP_COUNT := SP_COUNT + 1; end if; end if; exit when SP_COUNT = RESULTS_COUNT; end loop; end if; end SERIAL_POLL; begin accept START; INITIALIZE; RECEIVED_MESSAGE_PTR := new MESSAGE_LINK; loop WAIT_FOR_EVENT(THE_EVENT'address, -- The event is returned in the status THE_SERVICE_MASK); -- What we are waiting for -- if THE_EVENT.HW_STATUS(SRQI) and then if STATUS_BIT_SET(THE_EVENT,SRQI) and then not(OLD_SRQI) then SERIAL_POLL; end if; -- update the old for next loop -- OLD_SRQI := THE_EVENT.HW_STATUS(SRQI); OLD_SRQI := STATUS_BIT_SET(THE_EVENT,SRQI); select accept BUS_TRANSMIT; or accept SETUP_IEEE488_DEVICES (I488_DEVICES : in DEVICE_LIST) do ACTIVE_DEVICES := new DEVICE_LIST'(I488_DEVICES); end SETUP_IEEE488_DEVICES; SP_TALK_LENGTH := 0; for DEV in ACTIVE_DEVICES'range loop if ACTIVE_DEVICES(DEV).PROTOCOL = SRQ or ACTIVE_DEVICES(DEV).PROTOCOL = UATL then SP_TALK_BUFFER(SP_TALK_LENGTH) := DATA_BYTE(ACTIVE_DEVICES(DEV).ADDRESS + 64); -- Secondary address SP_TALK_BUFFER(SP_TALK_LENGTH+1) := 0; SP_TALK_LENGTH := SP_TALK_LENGTH + 1; end if; TERMINATION(ACTIVE_DEVICES(DEV).ADDRESS) := ACTIVE_DEVICES(DEV).TERMINATION; end loop; or delay 0.05; end select; while SEND_QUEUE.NEXT /= null loop if SEND_QUEUE.NEXT.MESSAGE.LENGTH > 0 then SET_LISTENER(SEND_QUEUE.NEXT.MESSAGE.RECEIVE); SET_TALKER(DEVICE_ID); HW_SEND(SEND_QUEUE,TX_STATUS); UNTALK_UNLISTEN; else TX_STATUS := OK; end if; if TX_STATUS = OK and SEND_QUEUE.NEXT.MESSAGE.RESPONSE = GET_RESPONSE then for USER in ID_TYPE'first..ID_TYPE'last loop if SEND_QUEUE.NEXT.MESSAGE.RECEIVE(USER) and TERMINATION(USER) = LF then SET_LISTENER(DEVICE_ID); SET_TALKER(USER); RECEIVE_MESSAGE (USER, STATUS, SEND_QUEUE.NEXT.TIME_OUT); UNTALK_UNLISTEN; end if; end loop; end if; if TX_STATUS = OK then QUEUE_TASK.DEQUEUE(SEND_QUEUE); end if; end loop; end loop; end CONTROLLER_488_TASK; end CONTROLLER_488;