;=======================================================================
;=======================================================================
; SERIAL PERIPHERAL INTERFACE (SPI) VIRTUAL PERIPHERALS
; SPIS (Authentic SPI Slave) Virtual Peripheral Demo Program
; Revision 1.02, 07.21.98
; Developed by Authentic Engineering for Scenix Semiconductor, Inc.
; Authentic Engineering // http://www.authenticeng.com // ak@silcom.com
;
;=======================================================================
;
; Authentic SPIS (SPI Slave) Virtual Peripheral
;
; SPIS is a part of the Authetic SPI virtual peripherals for SX micro.
; This VP provides simple and efficient way to send/get one word of
; data to/from SPI compatible MASTER device.
;
; SPIS is developed to work with relatively fast SPI devices. It
; occupies the CPU during the entire data transfer.
; Maximum clock rate is 1.1 MHz (900 nsec clock period). The clock
; rate may vary during data transfer cycle. The minimum clock rate
; is limited by the watchdog timer if it's enabled; or is unlimited
; otherwise.
;
; Word length can be set to anywhere from 1 to 16 bits. Longer word
; lengths could be easily implemented if needed.
;
; Clock polarity is configurable by using the appropriate command byte.
;
; Four I/O signal lines are associated with any SPI communication:
;
; Master-Out-Slave-In MOSI signal line
; Master-In-Slave_Out MISO signal line
; Serial Clock SCLK signal line
; Slave Select SS signal line
;
; SPIS does not make any diffenece between read and write cycles.
; The data is clocked in and out simultaneously.
;
; If necessary, user may want to add more sophistication to the data
; transfer by adding Read/Write and handshaking signals. All that
; can be easily implemented without affecting the core SPIS program.
;
; SPIS makes use of the Wake-UP interrupt from the SS signal,
; for this reason the SS signal must be assigned to one of the
; Port B pins. Other signals may use any pins of SX-28.
;
; To initialize the SPIS user must disable the RTCC interrupt and
; enable the appropriate edge wakeup interrupt from the SS pin.
; SPIS will then wait for the the interrupt from the SS input.
; When the interrupt occures, SPIS will start execution of the
; send/receive loop, waiting for SPI Clock signals and processing
; the incoming and outgoing data lines. After the predefined number
; of clock pulses SPIS will finish the communication cycle and
; exit the interrupt. In order to prevent locking of the driver
; in case of communication error, SPIS uses it's internal
; SPIS_WATCHDOG counter, which would expire if SPIS has not
; received the clock pulse for too long and the data transfer
; will be aborted.
;
; The two-byte (16 bits) send/receive buffer is allocated in
; memory as SPIS_LSB and SPIS_MSB. Data are shifted starting
; from the most significant bit.
; In case of less than 16-bit long data word, the SPIS will
; automatically align the MSBit of the word to the MSBit of
; the buffer before shifting. No user intervention is required.
; The contents of SPIS_LSB and SPIS_MSB are not preserved
; during the driver operation since the bits are always shifted in.
;
;
; -- SPIS control, status and I/O DATA registers --
;
; SPIS_WATCHDOG. This byte defines the timeout period for
; the SPI slave (see above). If SPIS will not receive the clock signal
; within this waiting period, the communication will be aborted and the
; error flag will be set. The actual timeout can be calculated as
; 160 nsec multiplied by SPIS_WATCHDOG.
;
; SPIS_PORTA_MASK, SPIS_PORTB_MASK, SPIS_PORTC_MASK. These
; bytes are the images of SX I/O ports direction registers.
; They are written to corresponding ports direction registers
; during SPIS initialisation.
;
; SPIS_WKUP_MASK - SPIS writes SPIS_WKUP_MASK into Wakeup Enable
; register of PortB
;
; SPIS_CMD - command and configuration byte. This byte defines:
; - SPI Clock polarity
; - direction (Read/Write)
; - number of bits to send/receive
;
; SPIS supports 4 commands, specified by the 4 MSBits of the
; SPIS_CMD byte:
;
; $1 - GET BYTE in SLAVE mode, define FALLING edge
; $5 - GET BYTE in SLAVE mode, define RISING edge
; $9 - SEND BYTE in SLAVE mode, define FALLING edge
; $D - SEND BYTE in SLAVE mode, define RISING edge
;
; Practically there is no difference between the GET and SEND commands.
; When the I/O buffer is shifted out, the input data is always
; shifted in. The different commands are provided for user convinience
; and confusion. The contents of SPIS_LSB and SPIS_MSB are
; not preserved during the driver operation since the bits are
; always shifted in even if they don't make any sense.
;
; Four LSBits of the command byte define the word length.
; $00 sets the length to 16 bits
; $01 sets the length to 1 bit
; ...
; $0F sets the length to 15 bits
;
; The SPIS_CMD byte also serves as a ready flag. SPIS will clear this
; byte upon the success of data transfer.
;
; SPIS_STATUS byte provides the error status information to the user
; program. It has 2 error flags:
; bit 4 - set to 1 when the SPIS_CMD byte contains an unsupported command
; bit 7 - set to 1 when the data transfer was not completed successfully
;
; -- SPIS ENTRY POINTS --
;
; SPIS_INIT - Initialization subroutine.It provides appropriate configuration
; for SX I/O ports.
;
; SPIS_EXECUTE - This is the actual VP entry point which is normally
; called from the interrupt service routine.
;
; SPIS_ORG. This is the base address of SPIM VP. Typically it will be
; next ROM location, after the user program.
;
; -- How to use SPIS from the user program --
;
; 1. Verify that the execution parameters are configured properly:
; SPIS_WATCHDOG
; SPIS_PORT_A_MASK
; SPIS_PORT_B_MASK
; SPIS_PORT_C_MASK
; SPIS_WKUP_MASK
; SPIS_CMD
;
; 2. Call SPIS_INIT
;
; 2. Verify that SPIS is ready for execution by testing the SPIS_CMD byte.
;
; 4. Place the outgoing data into SPIS_LSB and SPIS_MSB
;
; 5. Disable the RTCC interrupt and enable the SS interrupt from Port B.
;
; 6. Call SPIS_EXECUTE from the interrupt.
;
; 7. Test SPIS_CMD for completion and SPIS_STATUS for errors.
; Unload the data from SPIS_LSB and SPIS_MSB
;
; Your SPIS is now ready for reuse. Repeat from step 4.
;
;=======================================================================
;**************************** CODE START *******************************
;;recommended SX device configuration
; device pins28, pages4, banks8,oschs
; device turbo, stackx, optionx
; id 'SPIS_D3'
;reset reset_entry
;***************************** I/O PINS ********************************
;;example of SX I/O pins assingment
;spis_clk_pin = rb.0 ;SPI clock line
;spis_out_pin = rb.1 ;master_in slave_out line
;spis_in_pin = rb.2 ;master_out slave_in line
;spis_MCU_cs_pin = rb.3 ;slave select/slave request micro
;
;***********************************************************************
;************************** Authentic SPI SLAVE VP *********************
org 10h
spis_ram_bank = $
;SPIS control data
spis_cmd ds 1 ;SPIS command byte
fast_ON equ spis_cmd.4 ;always set to 1 for SPIS
master_ON equ spis_cmd.5 ;set to 1 if MASTER
rising_ON equ spis_cmd.6 ;set to 1 if RISING
transmit_ON equ spis_cmd.7 ;set to 1 if TRANSMIT
spis_watchdog ds 1 ;clock receive timeout
spis_port_b_mask ds 1 ;PortA direction register image
spis_port_a_mask ds 1 ;PortB direction register image
spis_port_c_mask ds 1 ;PortC direction register image
spis_wkup_mask ds 1 ;
;SPIS status data
spis_status ds 1 ;SPIS status byte
spis_cmd_error equ spis_status.4 ;error - unsupported command
spis_transfer_error equ spis_status.7 ;error - transfer aborted
;SPIS I/O buffer
spis_msb ds 1 ;I/O buffer MSByte
spis_lsb ds 1 ;I/O buffer LSByte
;SPIS private data
spis_bits_total ds 1 ;number of bits to transfer
spis_shift_counter ds 1 ;bit shift counter
spis_shifts_init ds 1 ;number or alignment shifts for the buffer
spis_watch_counter ds 1 ;watchdog counter
org spis_org
;********************* SPIS INITIALIZATION ROUTINE *********************
spis_init mov m,#$0f ;set up data direction registers
mov !rb,spis_port_b_mask ;configure ports
mov !ra,spis_port_a_mask
mov !rc,spis_port_c_mask
;configure the wakeup interrupt
mov m,#$0a ;set WKUP interrupt to FALLING edge
mov w,spis_wkup_mask
not w
mov !rb,w
mov m,#$0b ;enable interrupt
mov !rb,spis_wkup_mask
mov m,#$0f
ret
;************************* SPIS DATA TRANSFER **************************
spis_execute bank spis_ram_bank ;set SPIS RAM bank
mov m,#$09 ;clear pending interrupts
clr w
mov !rb,w
sb master_ON ;decode SPIS_CMD
jb fast_ON,spis_cmd_proc
setb spis_cmd_error ;set command error flag and exit
spis_exit clr spis_cmd ;clear SPIS_CMD and exit
ret
spis_cmd_proc
mov w,spis_cmd ;decode number of bits to transfer
and w,#$0f
mov spis_bits_total,w
test spis_bits_total
snz
mov spis_bits_total,#$10
mov spis_shift_counter,spis_bits_total
mov spis_shifts_init,#$10 ;decode number of bits to transfer
sub spis_shifts_init,spis_bits_total
test spis_shifts_init
jz :spis ;no initial shifts required
:set_bit_position ;align the word
clc
rl spis_lsb
rl spis_msb
djnz spis_shifts_init,:set_bit_position
:spis
test spis_shift_counter ;data transfer loop
jz :spis_execute_exit
jb rising_ON,:slave_rising ;jmp to rizing edge clock detection
:slave_falling ;falling edge active transfer
mov spis_watch_counter,spis_watchdog
:falling_send
jb spis_clk_pin,:shift_bit_out_on_fall
djnz spis_watch_counter,:falling_send
jmp :spis_error_exit ;exit when watchdog is zero
:shift_bit_out_on_fall ;shift bit out
movb spis_out_pin,spis_msb.7
rl spis_lsb
rl spis_msb
mov spis_watch_counter,spis_watchdog
:falling_get ;wait for falling edge to shift bit in
jnb spis_clk_pin,:shift_bit_in_on_fall
djnz spis_watch_counter,:falling_get
jmp :spis_error_exit ;exit when watchdog is zero
:shift_bit_in_on_fall
movb spis_lsb,spis_in_pin ;shift bit in
dec spis_shift_counter
jmp :spis ;next clock pulse
:slave_rising ;rising edge active data transfer
mov spis_watch_counter,spis_watchdog
:rising_send ;wait for falling edge to shift bit out
jnb spis_clk_pin,:shift_bit_out_on_rise
djnz spis_watch_counter,:rising_send
jmp :spis_error_exit ;exit when watchdog is zero
:shift_bit_out_on_rise
movb spis_out_pin,spis_msb.7 ;shift bit out
rl spis_lsb
rl spis_msb
mov spis_watch_counter,spis_watchdog
:rising_get ;wait for rising edge to shift bit in
jb spis_clk_pin,:shift_bit_in_on_rise
djnz spis_watch_counter,:rising_get
jmp :spis_error_exit ;exit when watchdog is zero
:shift_bit_in_on_rise
movb spis_lsb,spis_in_pin ;shift bit in
dec spis_shift_counter
jmp :spis ;next clock pulse
:spis_error_exit
setb spis_transfer_error ;exit on transfer error
mov w,#$01 ;error code is set
:spis_execute_exit
jmp spis_exit ;normal exit
ret ;TO CLOSE THE LABEL SCOPE
;***************************** END OF SPIS VP **************************
file: /Techref/scenix/spis.src, 11KB, , updated: 1999/2/20 12:23, local time: 2024/11/19 06:12,
|
| ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://linistepper.com/Techref/scenix/spis.src"> scenix spis</A> |
Did you find what you needed?
|