Author: sebastien.lelong
Date: Sat Jan  3 06:49:29 2009
New Revision: 710

Added:
    trunk/include/peripheral/i2c/i2c_hw_slave.jal
    trunk/include/peripheral/i2c/i2c_hw_slave_isr.jal

Log:
i2c slave lib + isr, first draft

Added: trunk/include/peripheral/i2c/i2c_hw_slave.jal
==============================================================================
--- (empty file)
+++ trunk/include/peripheral/i2c/i2c_hw_slave.jal       Sat Jan  3 06:49:29 2009
@@ -0,0 +1,77 @@
+-- Title: i2c_hardware slave procedures
+-- Author: Sebastien Lelong, Copyright (c) 2008-2009, all rights reserved.
+-- Adapted-by:
+-- Compiler: >=2.4i
+--
+-- This file is part of jallib (http://jallib.googlecode.com)
+-- Released under the ZLIB license  
(http://www.opensource.org/licenses/zlib-license.html)
+--
+-- Description: Common and useful functions and procedure to implement an  
I2C slave
+-- --
+-- /!\ i2c pins (SDA and SCL) must have been configured as input
+-- *before* including this file
+--
+
+
+-- setup an i2c slave, with low address (not high addresses coded with  
10-bits)
+--   - the passed address must be 8-bits long: it's a 7-bits address + the  
8th R/W bit
+--   - the start_stop_int argument can be set to true to generate  
START/STOP interrupts
+--     it's usually not necessary, and be useful to implement a master, or  
more importantly,
+--     can be used to debug an i2c bus (hardware bus check)
+procedure i2c_hw_slave_init(byte in height_bits_icaddress, bit in  
start_stop_int) is
+       -- For testing purpose (checking if slave is responding to START/STOP  
signals)
+       -- you may want to activate 7bits address with interrupts (see spec)
+       if start_stop_int
+       then
+               SSPCON1 = 0b_0011_1110  -- slave 7bit address, start/stop 
interrupt
+       else
+               SSPCON1 = 0b_0011_0110  -- slave 7bit address
+       end if
+       
+       -- I2C slave hardware
+       -- last 8th bits is for read/write setting.
+       -- I think it can be either 0 or 1, PIC does the job
+       SSPADD = height_bits_icaddress
+       
+       -- init SSPSTAT
+       SSPSTAT_BF = false
+       SSPCON1_WCOL = false
+       SSPCON1_SSPOV = false
+       PIR1_SSPIF = false
+       -- enable interrupts
+       PIE1_SSPIE = true
+       INTCON_GIE = true
+       INTCON_PEIE = true
+       
+end procedure  
+
+
+-- read a byte from i2c buffer and returns it
+function i2c_hw_slave_read_i2c() return byte is
+    var byte tmpbuf
+       tmpbuf = SSPBUF
+       return tmpbuf
+end function
+
+
+-- write a byte to i2c bus
+procedure i2c_hw_slave_write_i2c(byte in what) is
+       -- wait 'til buffer is empty
+       while SSPSTAT_BF loop end loop
+       var bit dosend = true
+       while dosend
+       loop
+               SSPCON1_WCOL = false
+               -- try to write into buffer, checking collision
+               SSPBUF = what
+               if ! SSPCON1_WCOL
+               then
+                       -- ok, done
+                       dosend = false
+               end if
+               -- else continue trying
+       end loop
+    SSPCON1_CKP = 1
+end procedure
+
+

Added: trunk/include/peripheral/i2c/i2c_hw_slave_isr.jal
==============================================================================
--- (empty file)
+++ trunk/include/peripheral/i2c/i2c_hw_slave_isr.jal   Sat Jan  3 06:49:29  
2009
@@ -0,0 +1,160 @@
+-- Title: i2c hardware slave ISR
+-- Author: Sebastien Lelong, Joep Suijs, Copyright (c) 2008-2009, all  
rights reserved.
+-- Adapted-by:
+-- Compiler: >=2.4i
+--
+-- This file is part of jallib (http://jallib.googlecode.com)
+-- Released under the ZLIB license  
(http://www.opensource.org/licenses/zlib-license.html)
+--
+-- Description: this library provides an ISR to implement
+-- a stateful i2c hardware slave. This is a jalv2 implementation of
+-- Microchip Application Note AN734.
+-- --
+-- According to AN734, there are 5 possible i2c states. During ISR, each
+-- of this states are detected. This ISR provides a standard skeleton to  
implement
+-- an i2c hardware slaves, while client code must implement several  
callbacks
+-- the ISR is expecting to call while processing states.
+-- --
+-- Here there are:
+--  - procedure i2c_hw_slave_on_master_talks(byte in _trash):
+--       called when i2c address matches (master starts a talk)
+--          => called in state 1
+--  - procedure i2c_hw_slave_on_master_writes(byte in rcv):
+--       called when master is writing a byte. Slave is thus
+--       receiving this byte. This callback takes this bytes as
+--       argument
+--          => called in state 2
+--  - procedure i2c_hw_slave_on_master_reads():
+--       called when master wants to read a byte from slave. Thus,
+--       slave should send a byte (for instance, using  
i2c_hw_slave_write_i2c
+--       from i2c_hw_slave.jal library)
+--          => called in state 3
+--  - procedure i2c_hw_slave_on_master_stillreads():
+--       called when master still wants to read a byte from slave. That is,
+--       master required to read (state 3) and now still want to read a  
byte
+--          => called in state 4
+--  - procedure i2c_hw_slave_on_master_hangsup():
+--       called when master does not want to talk to slave anymore
+--       usually a good place to reset data or slave's logic
+--          => called in state 5
+--  - procedure i2c_hw_slave_on_error():
+--       called when something wrong happens. You can do what you want in
+--       this case, like resetting the PIC, log some information using  
usart, ...
+--          => called any cases other than states 1, 2, 3, 4 or 5
+--
+--
+-- Sources:
+--   - AN734:
+--
+
+
+include i2c_hw_slave
+
+
+-- state 1: write operation, last byte is address, buffer full
+-- byte is an address, it we get here, we just know master
+-- wants to talk to us...
+-- and we also know address is recognized (BF is set, see spec)
+-- anyway, we must read buffer to reset BF bit
+--
+--     => call i2c_hw_slave_on_master_talks(byte)
+procedure i2c_hw_slave_proceed_state_1() is
+       pragma inline
+       var byte _trash = i2c_hw_slave_read_i2c()
+       i2c_hw_slave_on_master_talks(_trash)
+end procedure
+
+-- state 2: write operation, last byte is data, buffer full
+-- master wants to write, it sends a byte
+--
+--     => call i2c_hw_slave_on_master_writes(byte)
+procedure i2c_hw_slave_proceed_state_2() is
+       pragma inline
+       var byte rcv = i2c_hw_slave_read_i2c()
+       i2c_hw_slave_on_master_writes(rcv)
+end procedure
+
+
+-- state 3: read operation, last byte is address, buffer empty
+-- master wants to get a value from us
+--
+--     => call i2c_hw_slave_on_master_reads()
+procedure i2c_hw_slave_proceed_state_3() is
+       pragma inline
+       i2c_hw_slave_on_master_reads()
+end procedure
+
+
+-- state 4: read operation, last byte is data, buffer empty
+-- master still wants to get a value from us
+--
+--     => call i2c_hw_slave_on_master_stillreads()
+procedure i2c_hw_slave_proceed_state_4() is
+       pragma inline
+       i2c_hw_slave_on_master_stillreads()
+end procedure
+
+
+-- state 5: nack
+-- master doesn't want to talk with us anymore
+--
+--     => call i2c_hw_slave_on_master_hangsup()
+procedure i2c_hw_slave_proceed_state_5() is
+       pragma inline
+    -- AN734 does not talk about setting CKP, whereas spec says
+    -- it must be set. Some people say it can be error prone.
+    SSPCON1_CKP = 1
+       i2c_hw_slave_on_master_hangsup()
+end procedure
+
+
+-- state not recognized... Error !
+--
+--     => call i2c_hw_slave_on_error()
+procedure i2c_hw_slave_proceed_error() is
+       pragma inline
+       -- something went wrong, that is, XOR operations did not match
+       -- SSPSTAT bits
+       i2c_hw_slave_on_error()
+end procedure
+
+
+-- i2c ISR handler. Detects states a call appropriate procedures
+procedure i2c_hw_slave_isr_handler() is
+       pragma interrupt
+       if ! PIR1_SSPIF then
+               return
+       end if
+
+       PIR1_SSPIF = false
+    var byte tmpstat
+       tmpstat = SSPSTAT
+       -- mask out unimportant bit
+       tmpstat = tmpstat & 0b_0010_1101
+       -- check state 1: write operation, last byte is address, buffer full
+       if (tmpstat ^ 0b_0000_1001) == false
+       then
+               i2c_hw_slave_proceed_state_1()
+       -- check state 2: write operation, last byte is data, buffer full
+       elsif (tmpstat ^ 0b_0010_1001) == false
+       then
+               i2c_hw_slave_proceed_state_2()
+       -- check state 3: read operation, last byte is address, buffer empty
+       elsif (tmpstat ^ 0b_0000_1100) == false
+       then
+               i2c_hw_slave_proceed_state_3()
+       -- check state 4: read operation, last byte is data, buffer empty
+       elsif (tmpstat ^ 0b_00101100) == false
+       then
+               i2c_hw_slave_proceed_state_4()
+       -- check state 5: nack
+       elsif (tmpstat ^ 0b_0010_1000) == false
+       then
+               i2c_hw_slave_proceed_state_5()
+       -- check only got a start signal (when using interrupts)
+       else
+               i2c_hw_slave_proceed_error()
+       end if
+
+end procedure
+

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"jallib" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/jallib?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to