aboutsummaryrefslogtreecommitdiff
path: root/amforth-6.5/avr8/drivers
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2017-08-19 12:15:28 +0200
committerDimitri Sokolyuk <demon@dim13.org>2017-08-19 12:15:28 +0200
commit67d25d837ac55f28a366c0a3b262e439a6e75fc3 (patch)
treedf7715c7724c5935ab87c807f3b8b4ef529315e3 /amforth-6.5/avr8/drivers
parente0d6784e89dba33226c0edb815bb974486fa7c48 (diff)
Add AmForth
Diffstat (limited to 'amforth-6.5/avr8/drivers')
-rw-r--r--amforth-6.5/avr8/drivers/1wire.asm165
-rw-r--r--amforth-6.5/avr8/drivers/generic-isr.asm41
-rw-r--r--amforth-6.5/avr8/drivers/usart-rx-buffer.asm132
-rw-r--r--amforth-6.5/avr8/drivers/usart.asm30
-rw-r--r--amforth-6.5/avr8/drivers/usart_0.asm32
-rw-r--r--amforth-6.5/avr8/drivers/usart_1.asm31
-rw-r--r--amforth-6.5/avr8/drivers/usart_2.asm34
-rw-r--r--amforth-6.5/avr8/drivers/usart_3.asm31
-rw-r--r--amforth-6.5/avr8/drivers/usart_common.asm30
9 files changed, 526 insertions, 0 deletions
diff --git a/amforth-6.5/avr8/drivers/1wire.asm b/amforth-6.5/avr8/drivers/1wire.asm
new file mode 100644
index 0000000..ab5c9f4
--- /dev/null
+++ b/amforth-6.5/avr8/drivers/1wire.asm
@@ -0,0 +1,165 @@
+;; AUTHORs
+; B. J. Rodriguez (MSP 430)
+; Matthias Trute (AVR Atmega)
+; COPYRIGHT
+; (c) 2012 Bradford J. Rodriguez for the 430 code and API
+
+; adapted 430 assembly code to AVR
+; wishlist:
+; use a configurable pin at runtime, compatible with bitnames.frt
+; no external pull up, no external power supply for devices
+; ???
+;
+;.EQU OW_BIT=4
+;.equ OW_PORT=PORTE
+.set OW_DDR=(OW_PORT-1)
+.set OW_PIN=(OW_DDR-1)
+
+;****f* 1W.RESET
+; NAME
+; 1W.RESET
+; SYNOPSIS
+; 1W.RESET ( -- f ) Initialize 1-wire devices; return true if present
+; DESCRIPTION
+; This configures the port pin used by the 1-wire interface, and then
+; sends an "initialize" sequence to the 1-wire devices. If any device
+; is present, it will be detected.
+;
+; Timing, per DS18B20 data sheet:
+; a) Output "0" (drive output low) for >480 usec.
+; b) Output "1" (let output float).
+; c) After 15 to 60 usec, device will drive pin low for 60 to 240 usec.
+; So, wait 75 usec and sample input.
+; d) Leave output high (floating) for at least 480 usec.
+;******
+; ( -- f )
+; Hardware
+; Initialize 1-wire devices; return true if present
+VE_OW_RESET:
+ .dw $ff08
+ .db "1w.reset"
+ .dw VE_HEAD
+ .set VE_HEAD = VE_OW_RESET
+XT_OW_RESET:
+ .dw PFA_OW_RESET
+PFA_OW_RESET:
+ savetos
+ ; setup to output
+ sbi OW_DDR, OW_BIT
+ ; Pull output low
+ cbi OW_PORT, OW_BIT
+ ; Delay >480 usec
+ DELAY 480
+ ; Critical timing period, disable interrupts.
+ in temp1, SREG
+ cli
+ ; Pull output high
+ sbi OW_PORT, OW_BIT
+ ; make pin input, sends "1"
+ cbi OW_DDR, OW_BIT
+ DELAY 64 ; delayB
+ ; Sample input pin, set TOS if input is zero
+ in tosl, OW_PIN
+ sbrs tosl, OW_BIT
+ ser tosh
+ ; End critical timing period, enable interrupts
+ out SREG, temp1
+ ; release bus
+ cbi OW_DDR, OW_BIT
+ cbi OW_PORT, OW_BIT
+
+ ; Delay rest of 480 usec
+ DELAY 416
+ ; we now have the result flag in TOS
+ mov tosl, tosh
+ jmp_ DO_NEXT
+
+;****f* 1W.SLOT
+; NAME
+; 1W.SLOT
+; SYNOPSIS
+; 1W.SLOT ( c -- c' ) Write and read one bit to/from 1-wire.
+; DESCRIPTION
+; The "touch byte" function is described in Dallas App Note 74.
+; It outputs a byte to the 1-wire pin, LSB first, and reads back
+; the state of the 1-wire pin after a suitable delay.
+; To read a byte, output $FF and read the reply data.
+; To write a byte, output that byte and discard the reply.
+;
+; This function performs one bit of the "touch" operation --
+; one read/write "slot" in Dallas jargon. Perform this eight
+; times in a row to get the "touch byte" function.
+;
+; PARAMETERS
+; The input parameter is xxxxxxxxbbbbbbbo where
+; 'xxxxxxxx' are don't cares,
+; 'bbbbbbb' are bits to be shifted down, and
+; 'o' is the bit to be output in the slot. This must be 1
+; to create a read slot.
+;
+; The returned value is xxxxxxxxibbbbbbb where
+; 'xxxxxxxx' are not known (the input shifted down 1 position),
+; 'i' is the bit read during the slot. This has no meaning
+; if it was a write slot.
+; 'bbbbbbb' are the 7 input bits, shifted down one position.
+;
+; This peculiar parameter usage allows OWTOUCH to be written as
+; OWSLOT OWSLOT OWSLOT OWSLOT OWSLOT OWSLOT OWSLOT OWSLOT
+;
+; NOTES
+; Interrupts are disabled during each bit.
+
+; Timing, per DS18B20 data sheet:
+; a) Output "0" for start period. (> 1 us, < 15 us, typ. 6 us*)
+; b) Output data bit (0 or 1), open drain
+; c) After MS from start of cycle, sample input (15 to 60 us, typ. 25 us*)
+; d) After write-0 period from start of cycle, output "1" (>60 us)
+; e) After recovery period, loop or return. (> 1 us)
+; For writes, DS18B20 samples input 15 to 60 usec from start of cycle.
+; * "Typical" values are per App Note 132 for a 300m cable length.
+
+; --------- -------------------------------
+; \ / /
+; -------------------------------
+; a b c d e
+; | 6us | 19us | 35us | 2us |
+;******
+; ( c -- c' )
+; Hardware
+; Write and read one bit to/from 1-wire.
+VE_OW_SLOT:
+ .dw $ff07
+ .db "1w.slot",0
+ .dw VE_HEAD
+ .set VE_HEAD = VE_OW_SLOT
+XT_OW_SLOT:
+ .dw PFA_OW_SLOT
+PFA_OW_SLOT:
+ ; pull low
+ cbi OW_PORT, OW_BIT
+ sbi OW_DDR, OW_BIT
+ ; disable interrupts
+ in temp1, SREG
+ cli
+ DELAY 6 ; DELAY A
+ ; check bit
+ clc
+ ror tosl
+ brcc PFA_OW_SLOT0 ; a 0 keeps the bus low
+ ; release bus, a 1 is written
+ sbi OW_PORT, OW_BIT
+ cbi OW_DDR, OW_BIT
+PFA_OW_SLOT0:
+ ; sample the input (no action required if zero)
+ DELAY 9 ; wait DELAY E to sample
+ in temp0, OW_PIN
+ sbrc temp0, OW_BIT
+ ori tosl, $80
+
+ DELAY 51 ; DELAY B
+ sbi OW_PORT, OW_BIT ; release bus
+ cbi OW_DDR, OW_BIT
+ delay 2
+ ; re-enable interrupts
+ out SREG, temp1
+ jmp_ DO_NEXT
diff --git a/amforth-6.5/avr8/drivers/generic-isr.asm b/amforth-6.5/avr8/drivers/generic-isr.asm
new file mode 100644
index 0000000..e0aeaed
--- /dev/null
+++ b/amforth-6.5/avr8/drivers/generic-isr.asm
@@ -0,0 +1,41 @@
+; ISR routines
+.eseg
+intvec: .byte INTVECTORS * CELLSIZE
+.dseg
+intcnt: .byte INTVECTORS
+.cseg
+
+; interrupt routine gets called (again) by rcall! This gives the
+; address of the int-vector on the stack.
+isr:
+ st -Y, r0
+ in r0, SREG
+ st -Y, r0
+.if (pclen==3)
+ pop r0 ; some 128+K Flash devices use 3 cells for call/ret
+.endif
+ pop r0
+ pop r0 ; = intnum * intvectorsize + 1 (address following the rcall)
+ dec r0
+.if intvecsize == 1 ;
+ lsl r0
+.endif
+ mov isrflag, r0
+ push zh
+ push zl
+ ldi zl, low(intcnt)
+ ldi zh, high(intcnt)
+ lsr r0 ; we use byte addresses in the counter array, not words
+ add zl, r0
+ adc zh, zeroh
+ ld r0, Z
+ inc r0
+ st Z, r0
+ pop zl
+ pop zh
+
+ ld r0, Y+
+ out SREG, r0
+ ld r0, Y+
+ ret ; returns the interrupt, the rcall stack frame is removed!
+ ; no reti here, see words/isr-end.asm
diff --git a/amforth-6.5/avr8/drivers/usart-rx-buffer.asm b/amforth-6.5/avr8/drivers/usart-rx-buffer.asm
new file mode 100644
index 0000000..b6a64b8
--- /dev/null
+++ b/amforth-6.5/avr8/drivers/usart-rx-buffer.asm
@@ -0,0 +1,132 @@
+;;; usart driver, receiving
+
+; sizes have to be powers of 2!
+.equ usart_rx_size = $10
+.equ usart_rx_mask = usart_rx_size - 1
+.dseg
+ usart_rx_data: .byte usart_rx_size
+ usart_rx_in: .byte 1
+ usart_rx_out: .byte 1
+.cseg
+
+VE_TO_RXBUF:
+ .dw $ff07
+ .db ">rx-buf",0
+ .dw VE_HEAD
+ .set VE_HEAD = VE_TO_RXBUF
+XT_TO_RXBUF:
+ .dw PFA_rx_tobuf
+PFA_rx_tobuf:
+ mov temp0, tosl
+ lds temp1, usart_rx_in
+ ldi zl, low(usart_rx_data)
+ ldi zh, high(usart_rx_data)
+ add zl, temp1
+ adc zh, zeroh
+ st Z, temp0
+ inc temp1
+ andi temp1,usart_rx_mask
+ sts usart_rx_in, temp1
+ loadtos
+ jmp_ DO_NEXT
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; setup with
+; ' isr-rx URXCaddr int!
+VE_ISR_RX:
+ .dw $ff06
+ .db "isr-rx"
+ .dw VE_HEAD
+ .set VE_HEAD = VE_ISR_RX
+XT_ISR_RX:
+ .dw DO_COLON
+usart_rx_isr:
+ .dw XT_DOLITERAL
+ .dw usart_data
+ .dw XT_CFETCH
+ .dw XT_DUP
+ .dw XT_DOLITERAL
+ .dw 3
+ .dw XT_EQUAL
+ .dw XT_DOCONDBRANCH
+ .dw usart_rx_isr1
+ .dw XT_COLD
+usart_rx_isr1:
+ .dw XT_TO_RXBUF
+ .dw XT_EXIT
+
+; ( -- ) Hardware Access
+; R( --)
+; initialize usart
+;VE_USART_INIT_RXBUFFER:
+; .dw $ff0x
+; .db "+usart-buffer"
+; .dw VE_HEAD
+; .set VE_HEAD = VE_USART_INIT_RXBUFFER
+XT_USART_INIT_RX_BUFFER:
+ .dw DO_COLON
+PFA_USART_INIT_RX_BUFFER: ; ( -- )
+ .dw XT_DOLITERAL, XT_ISR_RX
+ .dw XT_DOLITERAL, URXCaddr
+ .dw XT_INTSTORE
+
+ .dw XT_DOLITERAL
+ .dw usart_rx_data
+ .dw XT_DOLITERAL
+ .dw usart_rx_size + 6
+ .dw XT_ZERO
+ .dw XT_FILL
+ .dw XT_EXIT
+
+; ( -- c)
+; MCU
+; get 1 character from input queue, wait if needed using interrupt driver
+VE_RX_BUFFER:
+ .dw $ff06
+ .db "rx-buf"
+ .dw VE_HEAD
+ .set VE_HEAD = VE_RX_BUFFER
+XT_RX_BUFFER:
+ .dw DO_COLON
+PFA_RX_BUFFER:
+ .dw XT_RXQ_BUFFER
+ .dw XT_DOCONDBRANCH
+ .dw PFA_RX_BUFFER
+ .dw XT_DOLITERAL
+ .dw usart_rx_out
+ .dw XT_CFETCH
+ .dw XT_DUP
+ .dw XT_DOLITERAL
+ .dw usart_rx_data
+ .dw XT_PLUS
+ .dw XT_CFETCH
+ .dw XT_SWAP
+ .dw XT_1PLUS
+ .dw XT_DOLITERAL
+ .dw usart_rx_mask
+ .dw XT_AND
+ .dw XT_DOLITERAL
+ .dw usart_rx_out
+ .dw XT_CSTORE
+ .dw XT_EXIT
+
+; ( -- f)
+; MCU
+; check if unread characters are in the input queue
+VE_RXQ_BUFFER:
+ .dw $ff07
+ .db "rx?-buf",0
+ .dw VE_HEAD
+ .set VE_HEAD = VE_RXQ_BUFFER
+XT_RXQ_BUFFER:
+ .dw DO_COLON
+PFA_RXQ_BUFFER:
+ .dw XT_PAUSE
+ .dw XT_DOLITERAL
+ .dw usart_rx_out
+ .dw XT_CFETCH
+ .dw XT_DOLITERAL
+ .dw usart_rx_in
+ .dw XT_CFETCH
+ .dw XT_NOTEQUAL
+ .dw XT_EXIT
diff --git a/amforth-6.5/avr8/drivers/usart.asm b/amforth-6.5/avr8/drivers/usart.asm
new file mode 100644
index 0000000..7274789
--- /dev/null
+++ b/amforth-6.5/avr8/drivers/usart.asm
@@ -0,0 +1,30 @@
+
+.equ BAUDRATE_LOW = UBRRL+$20
+.equ BAUDRATE_HIGH = UBRRH+$20
+.equ USART_C = UCSRC+$20
+.equ USART_B = UCSRB+$20
+.equ USART_A = UCSRA+$20
+.equ USART_DATA = UDR+$20
+.equ bm_USARTC_en = 1 << 7
+
+; some generic constants
+.equ bm_USART_RXRD = 1 << RXC
+.equ bm_USART_TXRD = 1 << UDRE
+.equ bm_ENABLE_TX = 1 << TXEN
+.equ bm_ENABLE_RX = 1 << RXEN
+.equ bm_ENABLE_INT_RX = 1<<RXCIE
+.equ bm_ENABLE_INT_TX = 1<<UDRE
+
+.equ bm_ASYNC = 0 << 6
+.equ bm_SYNC = 1 << 6
+.equ bm_NO_PARITY = 0 << 4
+.equ bm_EVEN_PARITY = 2 << 4
+.equ bm_ODD_PARITY = 3 << 4
+.equ bm_1STOPBIT = 0 << 3
+.equ bm_2STOPBIT = 1 << 3
+.equ bm_5BIT = 0 << 1
+.equ bm_6BIT = 1 << 1
+.equ bm_7BIT = 2 << 1
+.equ bm_8BIT = 3 << 1
+
+.include "drivers/usart_common.asm"
diff --git a/amforth-6.5/avr8/drivers/usart_0.asm b/amforth-6.5/avr8/drivers/usart_0.asm
new file mode 100644
index 0000000..107c462
--- /dev/null
+++ b/amforth-6.5/avr8/drivers/usart_0.asm
@@ -0,0 +1,32 @@
+ .equ BAUDRATE_LOW = UBRR0L
+ .equ BAUDRATE_HIGH = UBRR0H
+ .equ USART_C = UCSR0C
+ .equ USART_B = UCSR0B
+ .equ USART_A = UCSR0A
+ .equ USART_DATA = UDR0
+ .ifndef URXCaddr
+ .equ URXCaddr = URXC0addr
+ .equ UDREaddr = UDRE0addr
+ .endif
+
+.equ bm_USART_RXRD = 1 << RXC0
+.equ bm_USART_TXRD = 1 << UDRE0
+.equ bm_ENABLE_TX = 1 << TXEN0
+.equ bm_ENABLE_RX = 1 << RXEN0
+.equ bm_ENABLE_INT_RX = 1<<RXCIE0
+.equ bm_ENABLE_INT_TX = 1<<UDRIE0
+
+.equ bm_USARTC_en = 0
+.equ bm_ASYNC = 0 << 6
+.equ bm_SYNC = 1 << 6
+.equ bm_NO_PARITY = 0 << 4
+.equ bm_EVEN_PARITY = 2 << 4
+.equ bm_ODD_PARITY = 3 << 4
+.equ bm_1STOPBIT = 0 << 3
+.equ bm_2STOPBIT = 1 << 3
+.equ bm_5BIT = 0 << 1
+.equ bm_6BIT = 1 << 1
+.equ bm_7BIT = 2 << 1
+.equ bm_8BIT = 3 << 1
+
+.include "drivers/usart_common.asm"
diff --git a/amforth-6.5/avr8/drivers/usart_1.asm b/amforth-6.5/avr8/drivers/usart_1.asm
new file mode 100644
index 0000000..2ee44ae
--- /dev/null
+++ b/amforth-6.5/avr8/drivers/usart_1.asm
@@ -0,0 +1,31 @@
+ .equ BAUDRATE_LOW = UBRR1L
+ .equ BAUDRATE_HIGH = UBRR1H
+ .equ USART_C = UCSR1C
+ .equ USART_B = UCSR1B
+ .equ USART_A = UCSR1A
+ .equ USART_DATA = UDR1
+
+.equ URXCaddr = URXC1addr
+.equ UDREaddr = UDRE1addr
+
+.equ bm_USART_RXRD = 1 << RXC1
+.equ bm_USART_TXRD = 1 << UDRE1
+.equ bm_ENABLE_TX = 1 << TXEN1
+.equ bm_ENABLE_RX = 1 << RXEN1
+.equ bm_ENABLE_INT_RX = 1<<RXCIE1
+.equ bm_ENABLE_INT_TX = 1<<UDRIE1
+
+.equ bm_USARTC_en = 0
+.equ bm_ASYNC = 0 << 6
+.equ bm_SYNC = 1 << 6
+.equ bm_NO_PARITY = 0 << 4
+.equ bm_EVEN_PARITY = 2 << 4
+.equ bm_ODD_PARITY = 3 << 4
+.equ bm_1STOPBIT = 0 << 3
+.equ bm_2STOPBIT = 1 << 3
+.equ bm_5BIT = 0 << 1
+.equ bm_6BIT = 1 << 1
+.equ bm_7BIT = 2 << 1
+.equ bm_8BIT = 3 << 1
+
+.include "drivers/usart_common.asm"
diff --git a/amforth-6.5/avr8/drivers/usart_2.asm b/amforth-6.5/avr8/drivers/usart_2.asm
new file mode 100644
index 0000000..71fefe2
--- /dev/null
+++ b/amforth-6.5/avr8/drivers/usart_2.asm
@@ -0,0 +1,34 @@
+ .equ BAUDRATE_LOW = UBRR2L
+ .equ BAUDRATE_HIGH = UBRR2H
+ .equ USART_C = UCSR2C
+ .equ USART_B = UCSR2B
+ .equ USART_A = UCSR2A
+ .equ USART_DATA = UDR2
+
+ .equ URXCaddr = URXC2addr
+ .equ UDREaddr = UDRE2addr
+
+.equ bm_USART_RXRD = 1 << RXC2
+.equ bm_USART_TXRD = 1 << UDRE2
+.equ bm_ENABLE_TX = 1 << TXEN2
+.equ bm_ENABLE_RX = 1 << RXEN2
+.equ bm_ENABLE_INT_RX = 1<<RXCIE2
+.equ bm_ENABLE_INT_TX = 1<<UDRIE2
+
+.equ bm_USART_RXRD = 1 << RXC2
+.equ bm_USART_TXRD = 1 << UDRE2
+
+.equ bm_USARTC_en = 0
+.equ bm_ASYNC = 0 << 6
+.equ bm_SYNC = 1 << 6
+.equ bm_NO_PARITY = 0 << 4
+.equ bm_EVEN_PARITY = 2 << 4
+.equ bm_ODD_PARITY = 3 << 4
+.equ bm_1STOPBIT = 0 << 3
+.equ bm_2STOPBIT = 1 << 3
+.equ bm_5BIT = 0 << 1
+.equ bm_6BIT = 1 << 1
+.equ bm_7BIT = 2 << 1
+.equ bm_8BIT = 3 << 1
+
+.include "drivers/usart_common.asm"
diff --git a/amforth-6.5/avr8/drivers/usart_3.asm b/amforth-6.5/avr8/drivers/usart_3.asm
new file mode 100644
index 0000000..1745b31
--- /dev/null
+++ b/amforth-6.5/avr8/drivers/usart_3.asm
@@ -0,0 +1,31 @@
+ .equ BAUDRATE_LOW = UBRR3L
+ .equ BAUDRATE_HIGH = UBRR3H
+ .equ USART_C = UCSR3C
+ .equ USART_B = UCSR3B
+ .equ USART_A = UCSR3A
+ .equ USART_DATA = UDR3
+
+.equ URXCaddr = URXC3addr
+.equ UDREaddr = UDRE3addr
+
+.equ bm_USART_RXRD = 1 << RXC3
+.equ bm_USART_TXRD = 1 << UDRE3
+.equ bm_ENABLE_TX = 1 << TXEN3
+.equ bm_ENABLE_RX = 1 << RXEN3
+.equ bm_ENABLE_INT_RX = 1<<RXCIE3
+.equ bm_ENABLE_INT_TX = 1<<UDRIE3
+
+.equ bm_USARTC_en = 0
+.equ bm_ASYNC = 0 << 6
+.equ bm_SYNC = 1 << 6
+.equ bm_NO_PARITY = 0 << 4
+.equ bm_EVEN_PARITY = 2 << 4
+.equ bm_ODD_PARITY = 3 << 4
+.equ bm_1STOPBIT = 0 << 3
+.equ bm_2STOPBIT = 1 << 3
+.equ bm_5BIT = 0 << 1
+.equ bm_6BIT = 1 << 1
+.equ bm_7BIT = 2 << 1
+.equ bm_8BIT = 3 << 1
+
+.include "drivers/usart_common.asm"
diff --git a/amforth-6.5/avr8/drivers/usart_common.asm b/amforth-6.5/avr8/drivers/usart_common.asm
new file mode 100644
index 0000000..e6238ec
--- /dev/null
+++ b/amforth-6.5/avr8/drivers/usart_common.asm
@@ -0,0 +1,30 @@
+
+.set USART_C_VALUE = bm_ASYNC | bm_NO_PARITY | bm_1STOPBIT | bm_8BIT
+.if WANT_INTERRUPTS == 0
+ .if WANT_ISR_RX == 1
+ .error "*** Config error. set WANT_ISR_RX to 0 too if you disable interrupts (WANT_INTERRUPTS is set to 0)"
+ .endif
+.endif
+
+.if WANT_ISR_RX == 1
+ .set USART_B_VALUE = bm_ENABLE_TX | bm_ENABLE_RX | bm_ENABLE_INT_RX
+ .include "drivers/usart-rx-buffer.asm"
+; .include "drivers/timer-usart-isr.asm"
+ .set XT_RX = XT_RX_BUFFER
+ .set XT_RXQ = XT_RXQ_BUFFER
+ .set XT_USART_INIT_RX = XT_USART_INIT_RX_BUFFER
+.else
+ .set USART_B_VALUE = bm_ENABLE_TX | bm_ENABLE_RX
+ .include "words/usart-rx-poll.asm"
+ .set XT_RX = XT_RX_POLL
+ .set XT_RXQ = XT_RXQ_POLL
+ .set XT_USART_INIT_RX = 0
+.endif
+
+.include "words/usart-tx-poll.asm"
+.set XT_TX = XT_TX_POLL
+.set XT_TXQ = XT_TXQ_POLL
+.set XT_USART_INIT_TX = 0
+
+.include "words/ubrr.asm"
+.include "words/usart.asm"