Hello Helge,

Helge Kruse <helge.kr...@gmx.net> writes:

> Am 04.09.2021 um 14:38 schrieb Erich Wälde:
>
>> Using the serial interface for a rs485 connection ... now, that
>> I can understand :-) I have a collection of controllers "online",
>> descriptions start here (German text):
>> Vierte Dimension 2011/1
>> https://forth-ev.de/wiki/res/lib/exe/fetch.php/vd-archiv:4d2011-01.pdf
>> Judging from your name German text should not be a problem for you.
> Thanks for that hint. It's a very interesting article. I will experiment
> with it. Yep, German is no problem for me.
>> I'm very interested to hear, how you get along. Feel free to ask
>> about technical details.
>
> I read about the MPC and find it very interesting. Unfortunately I won't
> be able to use it, since the bus also uses broadcast addresses (126,127)
> and the MPC is specific to one address (intentionally).

Hmmm, you sure??? If I look at my code ... usart-isr-rx.asm ...
see below.

When "silent", the usart is set to 7N2. With mpc mode enabled
incoming data isr will call into usart_rx_isr WHENEVER the
highest bit of the address is set. The other 7 bits are passed
in register UDRn --- oh, oh, my reading avr assembly brain isn't
really awake ... --- and then the incoming Byte is compared to
ram_station_id. If it matches switch usart to 8N1, if not,
ignore.

Noone stops you from comparing to several such IDs, I think.


http://amforth.sourceforge.net/Projects/RS485/RS485Bus.html
has this as Forth code. In section 6 (handling an incoming byte
according to MPC-mode) you can better see the line, where the
decision is made:
| : mpc-rx-isr
|   rx-err? 0= if
|     UDR0 c@             \ -- udata
|     mpc? if
|       stationID = if  \ <== add more stationID tests here ...
|         -mpc7
|       then
|     else
|       rx-store
|     then
|   then
| ;


Unless I have misunderstood your text ...


Cheers,
Erich


--- usart-isr-rx.asm -------------------------------------------
;;; AmForth Version 4.5
;;; usart driver, receiving

.set pc_ = pc
.org URXCaddr
  jmp_ usart_rx_isr
.org pc_

; sizes have to be powers of 2!
.equ usart_rx_size = $10
.equ usart_rx_mask = usart_rx_size - 1
.dseg
usart_rx_in: .byte 1
usart_rx_out: .byte 1
usart_rx_data: .byte usart_rx_size
.cseg

.if WANT_MPC == 0              ; --- original version ---
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
usart_rx_isr:
  push xl
  in xl, SREG
  push xl
  push xh
  push zl
  push zh

  lds xh, USART_DATA
  ; optional: check for certain character(s) (e.g. CTRL-C)
  ; and trigger a soft interrupt instead of storing the
  ; charater into the input queue.
  lds xl,usart_rx_in
  ldi zl, low(usart_rx_data)
  ldi zh, high(usart_rx_data)
  add zl, xl
  adc zh, zeroh
  st Z, xh

  inc xl
  andi xl,usart_rx_mask

  sts usart_rx_in, xl

usart_rx_isr_finish:
  pop zh
  pop zl
  pop xh
  pop xl
  out SREG, xl
  pop xl
  reti

.else                          ; --- MPC version ---

usart_rx_isr:
       push xl                 ; save registers
       in xl, SREG
       push xl
       push xh
       push zl
       push zh
       push temp0

       in_ xh, UCSRA                   ; xh = UCSRnA
       mov temp0, xh                   ; temp0 = xh; save value

       andi xh, (1<<FE) | (1<<DOR) | (1<<PE) ; set zero flag

       lds xh, USART_DATA              ; xh = UDRn
       brne usart_rx_isr_finish        ; test Z flag, --> _finish on error 
(zero flag=0)

       lds xl,usart_rx_in              ; xl = i_in
       ldi zl, low(usart_rx_data)      ; Z = &buf[0]
       ldi zh, high(usart_rx_data)     ;
       add zl, xl                      ; Z += i_in
       adc zh, zeroh                   ; .

       sbrc temp0, MPCM                ; if (UCSRnA[MPCM] == 0)
       rjmp usart_rx_isr_mpcmode       ; {

       st Z, xh                        ; . buf[i_in] = xh (== UDRn); normal mode

       inc xl                          ; . xl += 1
       andi xl,usart_rx_mask           ; . xl %= siz (Ringbuffer)
       sts usart_rx_in, xl             ; . i_in = xl

       rjmp usart_rx_isr_finish        ; } else {

usart_rx_isr_mpcmode:                  ; multi-processor-communication mode 

       ldi zl, low(ram_station_id)          ; . Z = &ram_station_id
       ldi zh, high(ram_station_id)         ; . .
       ld  xl, Z                       ; . xl = ram_station_id
       cp  xl, xh                      ; . xl == xh?
       brne usart_rx_isr_finish        ; . if ( ram_station_id == UDRn )
       andi temp0, (~(1<<MPCM))        ; . { we are called!
       out_ UCSRA, temp0               ; . . UCSRA = temp0; clear MPCM
       ldi  temp0, (USART_C_VALUE)     ; . . temp0 = USARC_C_VALUE
       out_ UCSRC, temp0               ; . . UCSRC = temp0; 8N1 mode

usart_rx_isr_finish:                   ; } _finish

       pop temp0                       ; restore registers
       pop zh
       pop zl
       pop xh
       pop xl
       out SREG, xl
       pop xl

       reti

.endif
; ( -- ) Hardware Access
; R( --)
; initialize usart
;VE_USART_INIT_RX:
;  .dw $ff06
;  .db "+usart"
;  .dw VE_HEAD
;  .set VE_HEAD = VE_USART_INIT_RX
XT_USART_INIT_RX_ISR:
  .dw DO_COLON
PFA_USART_INIT_RX_ISR:          ; ( -- )
  .dw XT_ZERO
  .dw XT_DOLITERAL
  .dw usart_rx_in
  .dw XT_STORE

  .dw XT_EXIT

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

-- 
May the Forth be with you ...


_______________________________________________
Amforth-devel mailing list for http://amforth.sf.net/
Amforth-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/amforth-devel

Reply via email to