OpenCores
URL https://opencores.org/ocsvn/ssbcc/ssbcc/trunk

Subversion Repositories ssbcc

[/] [ssbcc/] [trunk/] [example/] [i2c/] [lib_i2c.s] - Diff between revs 2 and 5

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 2 Rev 5
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
; Copyright 2012, Sinclair R.F., Inc.
; Copyright 2012, 2014, Sinclair R.F., Inc.
;
;
; Major I2C functions:
; Major I2C functions:
;   i2c_send_start      ( - )
;   i2c_send_start      ( - )           send the start condition
;   i2c_send_byte       ( u - f )
;   i2c_send_restart    ( - )           send a restart after ACK during write
;   i2c_read_byte       ( - u )
;   i2c_send_byte       ( u - f )       send a byte (address, register, data, ...)
;   i2c_send_stop       ( - )
;   i2c_read_byte       ( f - u )       read a byte and either ACK (f=0) or STOP (f=1)
 
;   i2c_send_stop       ( - )           send a stop after ACK during write
 
;
 
; Example to set a single register (ignoring returned ACK/NACK value)
 
;   .call(i2c_send_start)
 
;   .call(i2c_send_byte,write_address) drop
 
;   .call(i2c_send_byte,register) drop
 
;   .call(i2c_send_byte,data) drop
 
;   .call(i2c_send_stop)
 
;
 
; Example to read two bytes (ignoring returned ACK/NACK value)
 
;   .call(i2c_send_start)
 
;   .call(i2c_send_byte,write_address) drop
 
;   .call(i2c_send_byte,register) drop
 
;   .call(i2c_send_restart)
 
;   .call(i2c_send_byte,read_address) drop
 
;   .call(i2c_read_byte,0)
 
;   .call(i2c_read_byte,1)
;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
; Compute how many iterations in the quarter-clock-cycle function are required.
; Compute how many iterations in the quarter-clock-cycle function are required.
;   ceil(100 MHz / 400 kHz / 4) ==> 63 clock cycles per I2C SCL quarter cycle
;   ceil(100 MHz / 400 kHz / 4) ==> 63 clock cycles per I2C SCL quarter cycle
;   The function consumes:
;   The function consumes:
;     3 clock cycles to call the function
;     3 clock cycles to call the function
;     3 clock cycles for the "outport(O_SCL)"
;     3 clock cycles for the "outport(O_SCL)"
;     1 clock cycle to initialize the loop count
;     1 clock cycle to initialize the loop count
;     2 clock cycles to return
;     2 clock cycles to return
;     9 TOTAL
;     9 TOTAL
;   Add 2 to ensure rounding up when evaluting the integer fraction.
;   Add 2 to ensure rounding up when evaluting the integer fraction.
;   The loop is 3 clock cycles per iteration
;   The loop is 3 clock cycles per iteration
 
.IFNDEF C_I2C_QUARTER_CYCLE
.constant C_I2C_QUARTER_CYCLE ${(63-9+2)/3}
.constant C_I2C_QUARTER_CYCLE ${(63-9+2)/3}
 
.ENDIF
 
 
; ( - )
; ( - )
.function i2c_send_start
.function i2c_send_start
  0 .outport(O_SDA)
  0 .outport(O_SDA)
  .call(i2c_quarter_cycle,1)
  .call(i2c_quarter_cycle,1)
  .call(i2c_quarter_cycle,0)
  .call(i2c_quarter_cycle,0)
.return
.return
 
 
; Set a start without the preceding stop.
; Set a start without the preceding stop.
; ( - )
; ( - )
.function i2c_send_restart
.function i2c_send_restart
  .call(i2c_quarter_cycle,0)
  .call(i2c_quarter_cycle,0)
  .call(i2c_quarter_cycle,1)
  .call(i2c_quarter_cycle,1)
  0 .outport(O_SDA) .call(i2c_quarter_cycle,1)
  0 .outport(O_SDA) .call(i2c_quarter_cycle,1)
  .call(i2c_quarter_cycle,0)
  .call(i2c_quarter_cycle,0)
.return
.return
 
 
; Send the byte and indicate false if the acknowledge bit was received.
; Send the byte and indicate false if the acknowledge bit was received.
; ( u - f )
; ( u - f )
.function i2c_send_byte
.function i2c_send_byte
  ; send the byte, msb first
  ; send the byte, msb first
  ; ( u - )
  ; ( u - )
  ${8-1} :outer
  ${8-1} :outer
    ; send the next bit
    ; send the next bit
    swap <<msb swap
    swap <<msb swap
    .call(i2c_clock_cycle,over) drop
    .call(i2c_clock_cycle,over) drop
  .jumpc(outer,1-) drop drop
  .jumpc(outer,1-) drop drop
  ; get the acknowledge bit at the middle of the high portion of SCL
  ; get the acknowledge bit at the middle of the high portion of SCL
  ; ( - f )
  ; ( - f )
  .call(i2c_clock_cycle,1)
  .call(i2c_clock_cycle,1)
.return
.return
 
 
; Read the next byte from the device.
; Read the next byte from the device and generate an ACK or a STOP.
; ( - u )
; ( f - u )
.function i2c_read_byte
.function i2c_read_byte
 
  ; Read 8 bits and pack them into the returned value.
 
  ; ( f - u f )
  0 ${8-1} :loop
  0 ${8-1} :loop
    swap <<0 .call(i2c_clock_cycle,1) or swap
    swap <<0 .call(i2c_clock_cycle,1) or swap
  .jumpc(loop,1-) drop
  .jumpc(loop,1-) drop
  ; send the acknowledgment bit
  swap
  .call(i2c_clock_cycle,0)
  ; Generate the ACK/STOP based on f.
.return(drop)
  ; ( u f - u )
 
  0 .outport(O_SDA)
 
  .call(i2c_quarter_cycle,0)
 
  .call(i2c_quarter_cycle,1)
 
  O_SDA outport
 
  .call(i2c_quarter_cycle,1)
 
  .call(i2c_quarter_cycle)      ; SCL is high on STOP, low on ACK, consumes f
 
.return
 
 
; Send a stop by bringing SDA high while SCL is high.
; Send a stop by bringing SDA high while SCL is high.
; ( - )
; ( - )
.function i2c_send_stop
.function i2c_send_stop
  0 .outport(O_SDA) .call(i2c_quarter_cycle,0)
  0 .outport(O_SDA) .call(i2c_quarter_cycle,0)
  .call(i2c_quarter_cycle,1)
  .call(i2c_quarter_cycle,1)
  1 .outport(O_SDA) .call(i2c_quarter_cycle,1)
  1 .outport(O_SDA) .call(i2c_quarter_cycle,1)
.return
.return
 
 
; Send the clock as a "0110" pattern and sample SDA in the middle of the high
; Send the clock as a "0110" pattern and sample SDA in the middle of the high
; portion.
; portion.
; ( u_sda_out - u_sda_in )
; ( u_sda_out - u_sda_in )
.function i2c_clock_cycle
.function i2c_clock_cycle
  .outport(O_SDA)
  .outport(O_SDA)
  .call(i2c_quarter_cycle,0)
  .call(i2c_quarter_cycle,0)
  .call(i2c_quarter_cycle,1)
  .call(i2c_quarter_cycle,1)
  .inport(I_SDA)
  .inport(I_SDA)
  .call(i2c_quarter_cycle,1)
  .call(i2c_quarter_cycle,1)
  .call(i2c_quarter_cycle,0)
  .call(i2c_quarter_cycle,0)
.return
.return
 
 
; Output the I2C SCL value and then wait for a quarter of the I2C clock cycle.
; Output the I2C SCL value and then wait for a quarter of the I2C clock cycle.
; ( u_scl - )
; ( u_scl - )
.function i2c_quarter_cycle
.function i2c_quarter_cycle
  .outport(O_SCL)
  .outport(O_SCL)
  ${C_I2C_QUARTER_CYCLE-1} :loop .jumpc(loop,1-)
  ${C_I2C_QUARTER_CYCLE-1} :loop .jumpc(loop,1-)
.return(drop)
.return(drop)
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.