External peripheral for enabling/disabling serial chip (MAX489) via pktEtx/pktErx

For past hardware configurations, we have been using PF5 on the Rabbit RCM3700 to enable and disable a MAX489 serial chip.

Packet.lib requires the functions pktEtx and pktErx to be defined by the user. In the past, this was done in a library that uses Packet.lib as follows:

nodebug void pktEtx() {EnableRS485Transmit(1);}
nodebug void pktErx() {EnableRS485Transmit(0);}

and EnableRS485Transmit() is defined using assembly language in another library as follows:


nodebug root void EnableRS485Transmit(int En)
{
   if (En == 1)
   {
      #asm
         push   ip                     ;save off IP state
         ipset   1                     ;set interrupt priority to level 1
         ld      a,(PFDRShadow)         ;get copy of shadow reg
         or      0x20                  ;set bit 5 high
         ld      (PFDRShadow),a         ;update shadow reg
         ioi   ld   (PFDR),a            ;set PF5 high
         pop   ip                     ;restore IP to the previous state
         ret
      #endasm
   }
   else
   {
      #asm
         push   ip                     ;save off IP state
         ipset   1                     ;set interrupt priority to level 1
         ld      a,(PFDRShadow)         ;get copy of shadow reg
         and   0xDF                  ;clear bit 5
         ld      (PFDRShadow),a         ;update shadow reg
         ioi   ld   (PFDR),a            ;set PF5 low
         pop   ip                     ;restore IP to the previous state
         ret
      #endasm
   }
}

The port for enabling/disabling the MAX489 chip has been relocated to an external I/O register. To reflect this change in the code, I have attempted to use C embedded within assembly as follows:


nodebug root void EnableRS485Transmit(int En)
{
   if (En == 1)
   {
      #asm
         push   ip                     ;save off IP state
         ipset   1                     ;set interrupt priority to level 1
         c   BitWrPortE(0x0003,&OutPort[1],1,2)
         pop   ip                     ;restore IP to the previous state
         ret
      #endasm
   }
   else
   {
      #asm
         push   ip                     ;save off IP state
         ipset   1                     ;set interrupt priority to level 1
         c   BitWrPortE(0x0003,&OutPort[1],0,2)
         pop   ip                     ;restore IP to the previous state
         ret
      #endasm
   }
}

BitWrPortE() is a SYSIO.lib function

The above method does not function correctly. Using a scope reveals that the enable pin on the MAX489 is usually held at low voltage, while it sometimes gets enabled for seemingly random durations of time, causing serial communications to fail. In our system, the serial enable pin should be oscillating many times a second to indicate status update packets are being sent regularly.

Does anyone have any suggestions as to how I can use an external address to define the functionality of pktEtx and pktErx for packet.lib?

Much appreciated,
Thanks

-Mike

If someone could show me how to properly write to an external register using Assembly languauge, that would be a huge help.

Thanks

Working with assembly is giving me a lot of trouble. I just don’t know enough about it to realize why I am seeing certain problems.

I’d like to attempt making pktEtx and pktErx work using just Dynamic C – no assembly. Is there any reason why I wouldn’t be able to do this?

If I define the following for packet.lib as described before:
nodebug void pktEtx() {EnableRS485Transmit(1);}
nodebug void pktErx() {EnableRS485Transmit(0);}

But this time I define EnableRS485Transmit() as follows:


nodebug root void EnableRS485Transmit(int En)
{
	BitWrPortI(PFDR,&PFDRShadow,En,5);
}

Is there any reason why this shouldn’t work?

When testing the above approach, it does not work. Sometimes the enable pin gets set and a packet gets sent, but most of the time nothing happens and serial communication fails.

Is this because I am not setting the interrupt priority as was done in the assembly code? Can I set the IP as required using just Dynamic C? If so, how would I do it?

Any help would be very much appreciated.

Thanks for looking.

To complete my thread in case anyone else will have similar questions in the future, here is how you write to an external register using assembly:


#asm
	push	ip		; Save-off IP state
	ipset	1		; Set interrupt priority to level 1
	ld	a,(PE0Shadow)	; Get copy of shadow register
	or	0x01		; Set shadow register bit 0
	ld	(PE0Shadow),a	; Update shadow register
	ld	bc, 0x0003	; Load BC w/ext addr of the control latch
	ioe	ld	(bc),a	; Set bit 0 on ext latch via addr 0x0003
	pop	ip		; Restore IP to the previous state
#endasm