; ; rs422code.asm -- code to drive the RS422 bus with data/strobe lines ; Copyright (C) 2002 Fred Barnes ; ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; this should be .include'd, and before such, define: ; OUT: PORT_NRE, BIT_NRE port and bit for !RE / DE (combined) ; IN: PIN_DRO, BIT_DRO pin and bit for DATA RECEIVE ; OUT: PORT_DDI, BIT_DDI port and bit for DATA TRANSMIT ; IN: PIN_SRO, BIT_SRO pin and bit for STROBE RECEIVE ; OUT: PORT_SDI, BIT_SDI port and bit for STROBE TRANSMIT ; I/O: DDR_NRE, DDR_DRO, DDR_DDI, DDR_SRO, DDR_SDI data-dir regs for all ; OUT: PORT_DRO, PORT_SRO ports for input pins ; COUNT: CHIP_TMHZ chip speed in integer (MHz times 10) ; IN: PIN_DDI,PIN_SDI maybe not needed, since they're output ; ; ; rs422_init. initialises RS422 stuff ; rs422_init: ; sort direction register bits out sbi DDR_NRE,BIT_NRE ; !RE/DE is output cbi PORT_NRE,BIT_NRE ; set !RE low, receive cbi DDR_DRO,BIT_DRO ; DRO is input sbi PORT_DRO,BIT_DRO ; enable pullup sbi DDR_DDI,BIT_DDI ; DDI is output cbi PORT_DDI,BIT_DDI ; set DDI low (irrelevant really) cbi DDR_SRO,BIT_SRO ; SRO is input sbi PORT_SRO,BIT_SRO ; enable pullup sbi DDR_SDI,BIT_SDI ; SDI is output cbi PORT_SDI,BIT_SDI ; set SDI low (irrelevant really) ret ; ; rs422_receive. puts RS422 line in receiver idle state. trashes r20 ; rs422_receive: cbi PORT_DDI,BIT_DDI ; DDI low cbi PORT_SDI,BIT_SDI ; SDI low cbi PORT_NRE,BIT_NRE ; disable transmit rjmp rs422_delay ; ; rs422_transmit. puts RS422 line in tramsmitter idle state. trashes r20 ; rs422_transmit: sbi PORT_DDI,BIT_DDI ; DDI high cbi PORT_SDI,BIT_SDI ; SDI low sbi PORT_NRE,BIT_NRE ; enable transmit rjmp rs422_delay ; ; rs422_dsstate. reads data-strobe state into r16 bits 0 and 1, ; leaves other bits alone ; rs422_dsstate: andi r16,0xfc ; clear bits 0 and 1 sbic PIN_DRO,BIT_DRO ori r16,0x01 sbic PIN_SRO,BIT_SRO ori r16,0x02 ret ; ; rs422_delay. delays for ~1ms (DEBUG speed!) ; rs422_delay: ldi r20,CHIP_TMHZ lsl r20 lsl r20 rs422_delay_l0: nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop dec r20 brne rs422_delay_l0 ; delay for 100us (DEBUG!, more like 1ms) ret ; ; rs422_tx. transmits a byte (r16) on the rs422 bus, including start and stop bits ; assumes transmit is already enabled (from rs422_idle). trashes r20,r21 ; rs422_tx: ; send out start bits (0110) clc rcall rs422_setbit sec rcall rs422_setbit sec rcall rs422_setbit clc rcall rs422_setbit mov r21,r16 ; shift out r21, MSB first lsl r21 rcall rs422_setbit lsl r21 rcall rs422_setbit lsl r21 rcall rs422_setbit lsl r21 rcall rs422_setbit lsl r21 rcall rs422_setbit lsl r21 rcall rs422_setbit lsl r21 rcall rs422_setbit lsl r21 rcall rs422_setbit ; send out stop bits (10) sec rcall rs422_setbit clc rcall rs422_setbit ; additional delay rcall rs422_delay rcall rs422_delay ret ; ; rs422_waitany. waits for a state change on the rs422 bus, sets carry flag accordingly ; trashes r20 and r21 ; rs422_waitany: ; wait for SRO to go high sbis PIN_SRO,BIT_SRO rjmp rs422_waitany ; read data pin clr r20 sbic PIN_DRO,BIT_DRO ser r20 ; wait for SRO to go low rs422_waitany_l0: sbic PIN_SRO,BIT_SRO rjmp rs422_waitany_l0 ; set carry accordingly and return clc sbrc r20,0 ; skip if DRO clear sec ret ; ; rs422_isidle. returns with carry set if the link is idle (delays for ~400us to check this) ; link idle state is simply no strobe for 400us. ; trashes r20,r21 ; rs422_isidle: ldi r21,CHIP_TMHZ lsl r21 ; r21 *= 2 rs422_isidle_l0: sbic PIN_SRO,BIT_SRO rjmp rs422_isidle_l1 sbic PIN_SRO,BIT_SRO rjmp rs422_isidle_l1 sbic PIN_SRO,BIT_SRO rjmp rs422_isidle_l1 sbic PIN_SRO,BIT_SRO rjmp rs422_isidle_l1 sbic PIN_SRO,BIT_SRO rjmp rs422_isidle_l1 sbic PIN_SRO,BIT_SRO rjmp rs422_isidle_l1 sbic PIN_SRO,BIT_SRO rjmp rs422_isidle_l1 ; didn't change, loop round for another go dec r21 brne rs422_isidle_l0 ; loop for another check ; no change for 400us or so sec ret rs422_isidle_l1: ; not idle clc ret ; ; rs422_setbit. puts carry bit on rs422 bus. ; assumes in transmit state or idle state ; rs422_setbit: brcs rs422_sb_l0 ; transmit zero cbi PORT_DDI,BIT_DDI ; set data low rjmp rs422_sb_l1 ; clock out ; transmit one rs422_sb_l0: sbi PORT_DDI,BIT_DDI ; set data high ; toggle strobe rs422_sb_l1: nop nop sbi PORT_SDI,BIT_SDI ; set strobe high ldi r20,CHIP_TMHZ lsl r20 ; r20 *= 2 rs422_sb_l2: nop nop dec r20 brne rs422_sb_l2 ; delay for ~80us cbi PORT_SDI,BIT_SDI ; set strobe low rjmp rs422_delay ; delay and return