DECUServe VMS Conference 3064.12

     
Next-Reply Prev-Reply    Next-Topic Prev-Topic    ConfDir-Paged-New>Old ConfDir-Paged-Old>New   ConfDir-All-New>Old ConfDir-All-Old>New
       
Directory of conferences This topic directory


Note 3064.12           X10 / X-10 / BSR / Home Automation               12 of 15

EISNER::COVERT "John.Covert@Compaq.com"             411 lines  17-JAN-2000 18:23

                            -< CM11.BLI Version 2 >-

--------------------------------------------------------------------------------

module cm11 (main = start, addressing_mode(external=general))=

begin



require 'sys$library:starlet';



macro 

    dsc_0 (buffer) = $BBLOCK[8] INITIAL (LONG(128), LONG(BUFFER)) %;



external routine

	lib$put_output;

forward routine

	read_mailbox:novalue,

	mailbox_ast:novalue,

	next_command:novalue,

	send_command:novalue,

	timer_ast:novalue;



GLOBAL

    checksum: byte,

    justsent: initial(0),

    awaitconfirm: initial(0),

    needtosend: initial(0),

    inputcoming: initial(0),

    chan: initial(0),

    mbxchan: initial(0),

    mbxiosb: VECTOR[4,word],

    cmdbuffer:  VECTOR[2,byte],

    cmdcount: initial(0),

    cmdptr,

    mbxbuffer:  VECTOR[128,byte],

    timeout: quad initial(0);



routine start =

begin



LOCAL

    status,

    iosb:    VECTOR[4,word],

    buffer:  VECTOR[128,byte],

    bufdesc:  dsc_0(buffer),

    ch: byte,

    noterms: quad initial(0);



!

! Create a mailbox to receive commands we need to send out on the CM11

!

! Remember to issue the following command before starting this

! And also to have SYSNAM privilege so it will work

! $ DEFINE/TABLE=LNM$PROCESS_DIRECTORY LNM$TEMPORARY_MAILBOX  LNM$SYSTEM

!

    status = $crembx(

			chan = mbxchan,

			lognam = %ascid'CM11_MAILBOX'

			);

    if not .status then SIGNAL_STOP(.status);



!

! Start the timeout routine

    timer_ast();

!

!

! Start the mailbox reading

!

    read_mailbox();



    status = $assign(devnam=%ascid'TERM_DEV',chan=chan);

    if not .status then SIGNAL_STOP(.status);



!

! Read forever

!

    while 1 do

	begin

	status = $qiow (

			chan   = .chan,

			func   = io$_readvblk,

			iosb   = iosb,

			p1     = buffer,

			p2     = 1);

	if not .status then SIGNAL_STOP(.status);

	if not .iosb[0] then signal_stop (.iosb[0]);



	$setast(enbflg=0);

	ch = .buffer[0];

!

! If we just sent something, this is supposed to be the checksum

!

	if .justsent

	then

	    begin

	    if .ch eqlu .checksum

	    then

		begin

		justsent = 0;

		awaitconfirm = 1;

		buffer[0] = 0;		! This command to the CM11 says OK!

		status = $qiow (

			chan   = .chan,

			func   = io$_writevblk,

			iosb   = iosb,

			p1     = buffer,

			p2     = 1);

		if not .status then SIGNAL_STOP(.status);

		if not .iosb[0] then signal_stop (.iosb[0]);

		end;

!

! Else we should send again, but do that a bit later

!

	    end;



!

! If the character indicates we have X10 data, go get it

!

	if .ch eqlu %x'5A' and .ch nequ .checksum

	then

	    begin

	    inputcoming = 1;

	    if .justsent or .awaitconfirm

	    then

		begin

		needtosend = 1;		! Sent command lost; we have to resend

		timeout = 0;		! Don't do it in the timer

		justsent = 0;

		end;

	    buffer[0] = %x'C3';		! This command to the CM11 gets the data

	    status = $qiow (

			chan   = .chan,

			func   = io$_writevblk,

			iosb   = iosb,

			p1     = buffer,

			p2     = 1);

	    if not .status then SIGNAL_STOP(.status);

	    if not .iosb[0] then signal_stop (.iosb[0]);

	    end;

!

! Format the output (we'll probably output it unless we had a count)

!

	bufdesc[dsc$w_length]=128;

	status = $fao (

			%ascid'!%D !XB',

			bufdesc[dsc$w_length],

			bufdesc,

			0,.ch);

	if not .status then SIGNAL_STOP(.status);

!

! Continue with main loop waiting for response

!

	if .inputcoming and .ch lequ 9 and .ch nequ 0 ! Expected response: count

	then

	    begin

	    !

	    ! Read the number of characters we were told to get

	    !

	    status = $qiow (

			chan   = .chan,

			func   = io$_readvblk,

			iosb   = iosb,

			p1     = buffer[1],

			p2     = .ch,

			p4     = noterms);

	    if not .status then SIGNAL_STOP(.status);

	    if not .iosb[0] then signal_stop (.iosb[0]);

	    bufdesc[dsc$w_length]=128;

	    status = $fao (

			%ascid'!%D !#(XB)',

			bufdesc[dsc$w_length],

			bufdesc,0,

			.ch+1,

			.ch,

			.buffer[1],

			.buffer[2],

			.buffer[3],

			.buffer[4],

			.buffer[5],

			.buffer[6],

			.buffer[7],

			.buffer[8],

			.buffer[9],

			);

	    if not .status then SIGNAL_STOP(.status);

	    inputcoming = 0;

	    end;

!

! Do some output (the received character or the received buffer)

!

	status = lib$put_output(bufdesc);

	if not .status then SIGNAL_STOP(.status);

!

! If the character indicates a powerfailure, reset the CM11 controller

!

	if .ch eqlu %x'A5' and .ch nequ .checksum

	then

	    begin

	    buffer[0] = %x'9B';		! This tells the CM11 to shut up

	    buffer[1] = 0;

	    buffer[2] = 0;

	    buffer[3] = 0;

	    buffer[4] = 0;

	    buffer[5] = 0;

	    buffer[6] = 0;

	    ! log it

	    status = $qiow (

			chan   = .chan,

			func   = io$_writevblk,

			iosb   = iosb,

			p1     = buffer,

			p2     = 7);

	    if not .status then SIGNAL_STOP(.status);

	    if not .iosb[0] then signal_stop (.iosb[0]);

	    bufdesc[dsc$w_length]=128;

	    status = $fao (

			%ascid'!%D 00 Power restored',

			bufdesc[dsc$w_length],

			bufdesc,0);

	    status = lib$put_output(bufdesc);

	    if not .status then SIGNAL_STOP(.status);

	    end;

!

! Zap our memory of the checksum; if the checksum was %x'5A' we need to

! treat a repeat of the same character as the incoming data indicator

! instead.  If it was %x'A5' we need to treat a repeat as the power

! failure indicator.  If it _was_ the checksum, we're already done with it.

!

	checksum = 0;

!

! If it's none of the above, and we just sent, then probably bad checksum

! Or, if input is no longer coming and we need to send, then it's probably

! then end of a receive, and now we can send.

!

	if not .inputcoming and (.justsent or .needtosend)

	then

	    send_command();	! Send it again



!

! If the character indicates the previous command we sent has completed,

! then get ready for more commands.

!

	if .ch eqlu %x'55' and .awaitconfirm

	then

	    begin

	    timeout = 0;

	    awaitconfirm = 0;

	    next_command();	! Get ready for the next command

	    end;



	$setast(enbflg=1);

	end;	! of endless loop



ss$_normal

end;



routine read_mailbox : novalue =

begin



local status;

    status = $qio (

			chan   = .mbxchan,

			func   = io$_readvblk,

			iosb   = mbxiosb,

			astadr = mailbox_ast,

			p1     = mbxbuffer,

			p2     = 128

			);

    if not .status then SIGNAL_STOP(.status);

end;



routine mailbox_ast : novalue =

begin



local

    status;



    if not .mbxiosb[0]

    then

        begin

        if .mbxiosb[0] EQLU SS$_ENDOFFILE

	then

	    begin

	    read_mailbox();

	    return;

	    end;

	signal_stop (.mbxiosb[0]);

        end

    else

        begin

        if .mbxiosb[1]

        then

	    begin

	    lib$put_output(%ascid'************************00 Odd bytect');

	    read_mailbox();

	    end

	else

	    begin

	    cmdcount = .mbxiosb[1]/2;

	    cmdptr = mbxbuffer;

	    next_command();

	    end;

	end;

end;



routine next_command: novalue =

begin

local

    c0: byte,

    c1: byte,

    c2: byte,

    status,

    buffer:  VECTOR[128,byte],

    bufdesc:  dsc_0(buffer);



    if .cmdcount leq 0

    then

	begin

	read_mailbox();		! Get more commands

	return;

	end;



    c0 = ..cmdptr;

    cmdbuffer[0] = .c0;

    cmdptr = .cmdptr+1;

    c1 = ..cmdptr;

    cmdbuffer[1] = .c1;

    cmdptr = .cmdptr+1;

    cmdcount = .cmdcount - 1;



    if .inputcoming

    then

	needtosend = 1		! Get it later

    else

	send_command();

    !

    ! Now format local output

    if .c0 eqlu 4  ! an address

    then

	begin

	bufdesc[dsc$w_length]=128;

	status = $fao (

			%ascid'!%D*!#(XB)',

			bufdesc[dsc$w_length],

			bufdesc,0,

			3,

			2,

			0,

			.c1

			);

	if not .status then SIGNAL_STOP(.status);

	end

    else			! a function

	begin

	bufdesc[dsc$w_length]=128;

	status = $fao (

			%ascid'!%D*!#(XB)',

			bufdesc[dsc$w_length],

			bufdesc,0,

			(if .c1<0,4,0> eqlu 4 or .c1<0,4,0> eqlu 5

				then (c2 = .c0<3,5,0>;

				     status=3)

				else status=2; .status+1), .status,

			1,

			.c1,

			.c2

			);

	if not .status then SIGNAL_STOP(.status);

	end;

	lib$put_output(bufdesc);

end;



routine timer_ast: novalue =

begin

local

    tvar: quad initial (-5000000),	! 1/2 second

    current_time: quad,

    status;

!

! Restart the AST for two seconds from now

!

    $setimr(daytim = tvar, astadr = timer_ast);

    if .timeout NEQU 0

    then

	begin

	$gettim(timadr = current_time);

	if .current_time GTRU .timeout

	then

	    send_command();  ! Send it again

	end;

end;



routine send_command: novalue =

begin

local

    current_time: quad,

    status;



    justsent = 1;

    checksum = .cmdbuffer[0] + .cmdbuffer[1];

    ! Send data; results will be processed in mainline code

    status = $qiow (

			chan   = .chan,

			func   = io$_writevblk,

			iosb   = mbxiosb,

			p1     = cmdbuffer,

			p2     = 2);

    if not .status then SIGNAL_STOP(.status);

    if not .mbxiosb[0] then signal_stop (.mbxiosb[0]);

    needtosend = 0;

    $gettim(timadr = current_time);

    timeout = .current_time + 20000000;	! Two seconds

end;



end

eludom


     
Next-Reply Prev-Reply    Next-Topic Prev-Topic    ConfDir-Paged-New>Old ConfDir-Paged-Old>New   ConfDir-All-New>Old ConfDir-All-Old>New
       
Directory of conferences This topic directory

DECUServe on-line conferencing system - consulting for peanuts

DECnotes Script provided by Roland Kessi, 21 February 1996