1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
|
//-----------------------------------------------------------------------------
// Copyright (C) 2009 Onno Kortmann <onno@gmx.net>
//
// 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.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
//
//-----------------------------------------------------------------------------
//
// IMPORTANT NOTE: This file is only to illustrate the simulavrxx<->verilog
// interface and is by no means any reference for anything whatsoever! It
// probably contains lots of bugs! As already stated above, there is no
// warranty!
//
//-----------------------------------------------------------------------------
.arch ATTiny25
#define __AVR_ATtiny25__ 1
#define __SFR_OFFSET 0
#include <avr/io.h>
#include "singlepincomm.h"
#if SPC_DEBUG
// some random TRX debugging... ;-)
.macro dbg1on
sbi PORTB, PB3
sbi DDRB, PB3
.endm
.macro dbg1off
cbi PORTB, PB3
sbi DDRB, PB3
.endm
.macro dbg2on
sbi PORTB, PB4
sbi DDRB, PB4
.endm
.macro dbg2off
cbi PORTB, PB4
sbi DDRB, PB4
.endm
#else
.macro dbg1on
.endm
.macro dbg1off
.endm
.macro dbg2on
.endm
.macro dbg2off
.endm
#endif
#include "singlepincomm.h"
#if SPC_CLISEI
#define CLI cli
#define SEI sei
#else
#define CLI
#define SEI
#endif
/* Receive one 'bit':
0. Switch to input
1. Wait for high state (no timeout)
2. Wait for low state, count this as highcnt
3. Wait for high state again, count this as lowcnt
4. Result is:
C=0 for a received zero (low phase longer than high phase)
C=1 otherwise
T=0 for everything ok
T=1 for timeout
*/
.global spc_recv_bit
spc_rx_bit:
dbg1on
clt
cbi SPC_DDR, SPC_BIT
#if SPC_RX_WAIT_INITIAL_HIGH
#if SPC_16BIT_TIME
clr lowcntl
#endif
clr lowcnth
;; wait for high (timeout when line is shorted to ground)
srb_waitinit:
sbic SPC_PIN, SPC_BIT
rjmp srb_waitinit_ready
#if SPC_16BIT_TIME
inc lowcntl
brne srb_waitinit
#endif
inc lowcnth
cpi lowcnth, SPC_RX_TIMEOUT
breq srb_timeout
rjmp srb_waitinit
srb_waitinit_ready:
#endif
#if SPC_16BIT_TIME
clr lowcntl
#endif
clr lowcnth
#if SPC_16BIT_TIME
clr highcntl
#endif
clr highcnth
;; wait for low
srb_wait0:
sbis SPC_PIN, SPC_BIT
rjmp srb_wait0_ready
#if SPC_16BIT_TIME
inc highcntl
brne srb_wait0
#endif
inc highcnth
cpi highcnth, SPC_RX_TIMEOUT
breq srb_timeout
rjmp srb_wait0
srb_wait0_ready:
;; wait for high
srb_wait1:
sbic SPC_PIN, SPC_BIT
rjmp srb_wait1_ready
#if SPC_16BIT_TIME
inc lowcntl
brne srb_wait1
#endif
inc lowcnth
cpi lowcnth, SPC_RX_TIMEOUT
breq srb_timeout
rjmp srb_wait1
srb_wait1_ready:
;; compare both times
cp lowcnth, highcnth
#if SPC16BIT_TIME
breq srb_compare_low
#endif
dbg1off
ret
#if SPC16BIT_TIME
srb_compare_low:
cp lowcntl, highcntl
#endif
dbg1off
ret
srb_timeout:
dbg1off
set
ret
.macro spc_short_delay
#if SPC_SWDELAY
mov temp0, spc_delay
#else
ldi temp0, SPC_TSVALUE
#endif
ll\@:
dec temp0
brne ll\@
.endm
/* Send one bit from carry. */
.global spc_tx_bit
spc_tx_bit:
dbg2on
;; start with transmission of high state
sbi SPC_PORT, SPC_BIT
sbi SPC_DDR, SPC_BIT
brcs tx1
tx0:
spc_short_delay
cbi SPC_PORT, SPC_BIT
ldi temp1, SPC_N
tx0l:
spc_short_delay
dec temp1
brne tx1l
;; high again - and input
spc_tx_end:
sbi SPC_PORT, SPC_BIT
cbi SPC_DDR, SPC_BIT
dbg2off
ret
tx1:
ldi temp1, SPC_N
tx1l:
spc_short_delay
dec temp1
brne tx1l
;; low
cbi SPC_PORT, SPC_BIT
spc_short_delay
;; and high again - and input
rjmp spc_tx_end
// FIXME: Combine spc_trx_master and spc_trx_slave into one procedure!
/* Do a complete transmit/receive for one byte as the master. This means
synchronizing with the slave (sending and receiving one start-zero) and
transmitting/receiving the content from/into trxbyte. */
.section .text.spc_trx_master
.global spc_trx_master
spc_trx_master:
CLI
;; send start zero
clc
rcall spc_tx_bit
;; receive start zero
rcall spc_rx_bit
brts mspc_trx_end ; T=1 -> timeout ->failure
ldi bitcnt, 8
mtrxloop:
;; fetch next bit from trxbyte and send it
lsr trxbyte
rcall spc_tx_bit
rcall spc_rx_bit
brts mspc_trx_end ; handle timeouts
brcc mtrx_looptail ; zero received -> nothing to do
ori trxbyte, 0x80 ; push one into highest bit.. will rotate through to lower bits
mtrx_looptail:
dec bitcnt
brne mtrxloop
mspc_trx_end:
SEI
ret
/* Do a complete transmit/receive for one byte as the slaver. This means
synchronizing with the master (receiving and sending one start-zero) and
transmitting/receiving the content from/into trxbyte. */
.section .text.spc_trx_slave
.global spc_trx_slave
spc_trx_slave:
CLI
;; receive start zero
rcall spc_rx_bit
brts sspc_trx_end ; -> failure
;; send start zero
clc
rcall spc_tx_bit
ldi bitcnt, 8
strxloop:
rcall spc_rx_bit
brts sspc_trx_end ; handle timeouts
ror trxbyte ; stuff it into the trxbyte
rcall spc_tx_bit ; and transmit what fell out of the register at the other end
dec bitcnt
brne strxloop
sspc_trx_end:
SEI
ret
|