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
-~----------~----~----~----~------~----~------~--~---