;======================================================================= ;======================================================================= ; SERIAL PERIPHERAL INTERFACE (SPI) VIRTUAL PERIPHERALS ; DEMO3S.SRC -- Demo #3 Slave SX Software ; 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 ; ;======================================================================= ;======================================================================= ; ; DEMO#3 provides an example of data transfer between two ; SX microcontrollers through the SPI data bus. ; DEMO#3 consists of two programs - DEMO3M.SRC and DEMO3S.SRC, ; which correspond to the SPI Master and SPI Slave sides accordingly. ; The are 4 signal lines that connect the Master to the Slave: ; ; Master-Out-Slave-In MOSI signal line ; Master-In-Slave_Out MISO signal line ; Serial Clock SCLK signal line ; Slave Select SS signal line ; ; The Slave Select (SS) Line from Master to Slave signals the ; latter to start sending/receiving data. The word length is set ; to 16 bits in this demo (VP permits 1 to 16 bits). ; ; Authentic SPI virtual perphirals perform shifting in and out at ; the same time, as most hardware SPI implemetations do. ; ; The demo works as follows: ; - Assuming that Slave has been initialized prior to Master, ; the Master sends The Predefined Word 256 times. ; - The Slave SX is configured to perform the loopback function, ; that is, every time Slave sends to the Master whatever it has ; received from the Master during the previous transmission. ; - After the initial 256 transmissions Master switches into ; the loopback mode. ; - The data transfer of Predefined Word can be easily observed ; with the help of oscilloscope. ; ; SPI clock period for this demo is 900 nsec - maximum clock ; rate supported by the SPIS (SPI Slave VP). ; ; Data transfer from Master side is triggered by RTCC interrupt with ; a period of 25.6 microseconds. ; ;======================================================================= ; ; 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 ; ... ; 0ドルF 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 ******************************* device pins28, pages4, banks8,oschs device turbo, stackx, optionx id 'SPIS_D3' reset reset_entry ;***************************** I/O PINS ******************************** 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 ;******************************* RAM *********************************** ;SPIS DEMO#3 Variables. org 8 spis_demo_watchdog ds 1 ;DEMO#3 watchdog value (04ドル) spis_demo_cmd ds 1 ;DEMO#3 SPIS_CMD (50ドル) ;************************* INTERRUPT HANDLER *************************** ;Calls the SPIS_S driver and exits org 0 call spis_execute reti ;************************ DEMO#3 MAIN PROGRAM ************************** reset_entry mov !option,#40ドル ;disable RTCC interrupt clr fsr ;clear RAM :loop setb fsr.4 clr ind ijnz fsr,:loop ;Set SPIS control registers and reset the driver bank spis_ram_bank mov spis_port_b_mask,#$fd mov spis_wkup_mask,#$f7 mov spis_demo_watchdog,#4ドル mov spis_demo_cmd,#50ドル ;GET RISING 16 BIT ; mov spis_demo_cmd,#1ドルc ;GET FALLING 12 BIT call spis_init ;initialize WATCHDOG mov spis_watchdog,spis_demo_watchdog ;Main loop main_slave call :spis_transfer ;main program loop jmp main_slave ;SPIS restart :spis_transfer test spis_cmd ;wait for SPIM to be ready jnz :spis_transfer ;for next transfer mov spis_cmd,spis_demo_cmd ;initialize SPI_CMD ret spis_org equ $ ;*********************************************************************** ;************************** 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,#0ドルf ;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,#0ドルa ;set WKUP interrupt to FALLING edge mov w,spis_wkup_mask not w mov !rb,w mov m,#0ドルb ;enable interrupt mov !rb,spis_wkup_mask mov m,#0ドルf 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,#0ドルf 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 **************************
.