changeset 165:ad7069f53e31 main

New sensor package to read the LSI LS7366 quadrature counter via SPI.
author Bob Cook <bob@bobcookdev.com>
date Thu, 27 Dec 2012 15:12:51 -0800
parents 13020c7be732
children 586104541d77
files main/packages/avr/sensors/jamdefs main/packages/avr/sensors/ls7366/jamfile main/packages/avr/sensors/ls7366/ls7366.cpp main/packages/avr/sensors/ls7366/ls7366.h
diffstat 4 files changed, 643 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/main/packages/avr/sensors/jamdefs	Sun Nov 11 09:07:21 2012 -0800
+++ b/main/packages/avr/sensors/jamdefs	Thu Dec 27 15:12:51 2012 -0800
@@ -5,7 +5,7 @@
 #   Bob Cook Development, Robotics Library
 #   http://www.bobcookdev.com/rl/
 #
-#   Copyright (c) 2010 Bob Cook
+#   Copyright (c) 2010-2012 Bob Cook
 #   
 #   Permission is hereby granted, free of charge, to any person obtaining a copy
 #   of this software and associated documentation files (the "Software"), to deal
@@ -31,7 +31,7 @@
 
 # -----------------------------------------------------------------------------------------
 
-DefinePackages TOP packages avr sensors : sca3000 ;
+DefinePackages TOP packages avr sensors : ls7366 sca3000 ;
 
 # -----------------------------------------------------------------------------------------
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/packages/avr/sensors/ls7366/jamfile	Thu Dec 27 15:12:51 2012 -0800
@@ -0,0 +1,39 @@
+# -----------------------------------------------------------------------------------------
+#
+#   Copyright (C) 2012 Bob Cook
+#
+#   Bob Cook Development, Robotics Library
+#   http://www.bobcookdev.com/rl/
+#    
+#   Permission is hereby granted, free of charge, to any person obtaining a copy
+#   of this software and associated documentation files (the "Software"), to deal
+#   in the Software without restriction, including without limitation the rights
+#   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#   copies of the Software, and to permit persons to whom the Software is
+#   furnished to do so, subject to the following conditions:
+#
+#   The above copyright notice and this permission notice shall be included in
+#   all copies or substantial portions of the Software.
+#
+#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#   THE SOFTWARE.
+#
+# -----------------------------------------------------------------------------------------
+
+if $(TRACE) { echo "trace /packages/avr/sensors/ls7366/jamfile" ; }
+
+SubDir TOP packages avr sensors ls7366 ;
+
+# -----------------------------------------------------------------------------------------
+
+PackageSources
+    ls7366.cpp
+    ;
+
+# -----------------------------------------------------------------------------------------
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/packages/avr/sensors/ls7366/ls7366.cpp	Thu Dec 27 15:12:51 2012 -0800
@@ -0,0 +1,473 @@
+// ----------------------------------------------------------------------------------------
+//
+//  Copyright (C) 2012 Bob Cook
+//    
+//  Bob Cook Development, Robotics Library
+//  http://www.bobcookdev.com/rl/
+// 
+//  Control for the LSI LS7366 Quadrature Decoder / Counter
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+// 
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+// 
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+// ----------------------------------------------------------------------------------------
+
+#include "ls7366.h"
+
+#include <avr/io.h>
+
+#include "packages/avr/device/spi.h"
+#include "packages/avr/device/spinwait.h"
+
+// ----------------------------------------------------------------------------------------
+
+#include "project_defs.h"
+
+#if defined( PRJ_LS7366_ENABLE )
+
+#if !defined( PRJ_LS7366_ENABLE_CHIP_1 ) && !defined( PRJ_LS7366_ENABLE_CHIP_2 ) && \
+    !defined( PRJ_LS7366_ENABLE_CHIP_3 ) && !defined( PRJ_LS7366_ENABLE_CHIP_4 )
+#error At least one PRJ_LS7366_ENABLE_CHIP_x is required!
+#endif
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_1 )
+
+#if !defined( PRJ_LS7366_SELECT_1_DDR )
+#error PRJ_LS7366_SELECT_1_DDR is required!
+#endif
+
+#if !defined( PRJ_LS7366_SELECT_1_PORT )
+#error PRJ_LS7366_SELECT_1_PORT is required!
+#endif
+
+#if !defined( PRJ_LS7366_SELECT_1_PIN )
+#error PRJ_LS7366_SELECT_1_PIN is required!
+#endif
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_1 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_2 )
+
+#if !defined( PRJ_LS7366_SELECT_2_DDR )
+#error PRJ_LS7366_SELECT_2_DDR is required!
+#endif
+
+#if !defined( PRJ_LS7366_SELECT_2_PORT )
+#error PRJ_LS7366_SELECT_2_PORT is required!
+#endif
+
+#if !defined( PRJ_LS7366_SELECT_2_PIN )
+#error PRJ_LS7366_SELECT_2_PIN is required!
+#endif
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_2 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_3 )
+
+#if !defined( PRJ_LS7366_SELECT_3_DDR )
+#error PRJ_LS7366_SELECT_3_DDR is required!
+#endif
+
+#if !defined( PRJ_LS7366_SELECT_3_PORT )
+#error PRJ_LS7366_SELECT_3_PORT is required!
+#endif
+
+#if !defined( PRJ_LS7366_SELECT_3_PIN )
+#error PRJ_LS7366_SELECT_3_PIN is required!
+#endif
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_3 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_4 )
+
+#if !defined( PRJ_LS7366_SELECT_4_DDR )
+#error PRJ_LS7366_SELECT_4_DDR is required!
+#endif
+
+#if !defined( PRJ_LS7366_SELECT_4_PORT )
+#error PRJ_LS7366_SELECT_4_PORT is required!
+#endif
+
+#if !defined( PRJ_LS7366_SELECT_4_PIN )
+#error PRJ_LS7366_SELECT_4_PIN is required!
+#endif
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_4 )
+
+#endif // #if defined( PRJ_LS7366_ENABLE )
+
+// ----------------------------------------------------------------------------------------
+//  Refer to the LSI LS7366 datasheet for details.
+//
+//  http://www.lsicsi.com/pdfs/LS7366.pdf
+//
+
+static const uint8_t LS7366_CMD_CLEAR_MDR0 = 0b00001000;
+static const uint8_t LS7366_CMD_CLEAR_MDR1 = 0b00010000;
+static const uint8_t LS7366_CMD_CLEAR_CNTR = 0b00100000;
+static const uint8_t LS7366_CMD_CLEAR_STR  = 0b00110000;
+
+const uint8_t LS7366_CMD_READ_MDR0  = 0b01001000;
+const uint8_t LS7366_CMD_READ_MDR1  = 0b01010000;
+const uint8_t LS7366_CMD_READ_CNTR  = 0b01100000;
+const uint8_t LS7366_CMD_READ_OTR   = 0b01101000;
+const uint8_t LS7366_CMD_READ_STR   = 0b01110000;
+
+const uint8_t LS7366_CMD_WRITE_MDR0 = 0b10001000;
+const uint8_t LS7366_CMD_WRITE_MDR1 = 0b10010000;
+const uint8_t LS7366_CMD_WRITE_DTR  = 0b10011000;
+
+const uint8_t LS7366_CMD_LOAD_CNTR  = 0b10100000;
+const uint8_t LS7366_CMD_LOAD_OTR   = 0b10101000;
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_1 )
+
+static inline void select_chip_1() __attribute__((always_inline));
+static inline void select_chip_1()
+{
+    PRJ_LS7366_SELECT_1_PORT &= ~( 1 << PRJ_LS7366_SELECT_1_PIN );
+}
+
+static inline void deselect_chip_1() __attribute__((always_inline));
+static inline void deselect_chip_1()
+{
+    PRJ_LS7366_SELECT_1_PORT |= ( 1 << PRJ_LS7366_SELECT_1_PIN );
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_1 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_2 )
+
+static inline void select_chip_2() __attribute__((always_inline));
+static inline void select_chip_2()
+{
+    PRJ_LS7366_SELECT_2_PORT &= ~( 1 << PRJ_LS7366_SELECT_2_PIN );
+}
+
+static inline void deselect_chip_2() __attribute__((always_inline));
+static inline void deselect_chip_2()
+{
+    PRJ_LS7366_SELECT_2_PORT |= ( 1 << PRJ_LS7366_SELECT_2_PIN );
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_2 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_3 )
+
+static inline void select_chip_3() __attribute__((always_inline));
+static inline void select_chip_3()
+{
+    PRJ_LS7366_SELECT_3_PORT &= ~( 1 << PRJ_LS7366_SELECT_3_PIN );
+}
+
+static inline void deselect_chip_3() __attribute__((always_inline));
+static inline void deselect_chip_3()
+{
+    PRJ_LS7366_SELECT_3_PORT |= ( 1 << PRJ_LS7366_SELECT_3_PIN );
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_3 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_4 )
+
+static inline void select_chip_4() __attribute__((always_inline));
+static inline void select_chip_4()
+{
+    PRJ_LS7366_SELECT_4_PORT &= ~( 1 << PRJ_LS7366_SELECT_4_PIN );
+}
+
+static inline void deselect_chip_4() __attribute__((always_inline));
+static inline void deselect_chip_4()
+{
+    PRJ_LS7366_SELECT_4_PORT |= ( 1 << PRJ_LS7366_SELECT_4_PIN );
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_4 )
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_LS7366_ENABLE )
+
+void ls7366_init()
+{
+    //--    Initialize the SPI bus (doesn't matter if the caller did it already).
+
+    spi_init();
+
+    //--    Configure the select line and Reset all of the defined LS7366 chips.
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_1 )
+
+    PRJ_LS7366_SELECT_1_DDR |= ( 1 << PRJ_LS7366_SELECT_1_PIN );
+    deselect_chip_1();
+
+    ls7366_reset_1();
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_1 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_2 )
+
+    PRJ_LS7366_SELECT_2_DDR |= ( 1 << PRJ_LS7366_SELECT_2_PIN );
+    deselect_chip_2();
+
+    ls7366_reset_2();
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_2 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_3 )
+
+    PRJ_LS7366_SELECT_3_DDR |= ( 1 << PRJ_LS7366_SELECT_3_PIN );
+    deselect_chip_3();
+
+    ls7366_reset_3();
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_3 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_4 )
+
+    PRJ_LS7366_SELECT_4_DDR |= ( 1 << PRJ_LS7366_SELECT_4_PIN );
+    deselect_chip_4();
+
+    ls7366_reset_4();
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_4 )
+
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE )
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_LS7366_ENABLE )
+
+void ls7366_stop()
+{
+    spi_stop();
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE )
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_1 )
+
+void ls7366_reset_1()
+{
+    select_chip_1();
+    spi_write( LS7366_CMD_CLEAR_STR );
+    deselect_chip_1();
+    
+    select_chip_1();
+    spi_write( LS7366_CMD_CLEAR_MDR0 );
+    deselect_chip_1();
+
+    select_chip_1();
+    spi_write( LS7366_CMD_CLEAR_MDR1 );
+    deselect_chip_1();
+
+    select_chip_1();
+    spi_write( LS7366_CMD_CLEAR_CNTR );
+    deselect_chip_1();
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_1 )
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_1 )
+
+uint32_t ls7366_read_counter_1()
+{
+    select_chip_1();
+    spi_write( LS7366_CMD_LOAD_OTR );
+    deselect_chip_1();
+
+    select_chip_1();
+    spi_write( LS7366_CMD_READ_OTR );
+
+    uint32_t value = spi_read();
+    value = ( value << 8 ) | spi_read();
+    value = ( value << 8 ) | spi_read();
+    value = ( value << 8 ) | spi_read();
+
+    deselect_chip_1();
+
+    return value;
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_1 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_2 )
+
+uint32_t ls7366_read_counter_2()
+{
+    select_chip_2();
+    spi_write( LS7366_CMD_LOAD_OTR );
+    deselect_chip_2();
+
+    select_chip_2();
+    spi_write( LS7366_CMD_READ_OTR );
+
+    uint32_t value = spi_read();
+    value = ( value << 8 ) | spi_read();
+    value = ( value << 8 ) | spi_read();
+    value = ( value << 8 ) | spi_read();
+
+    deselect_chip_2();
+
+    return value;
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_2 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_3 )
+
+uint32_t ls7366_read_counter_3()
+{
+    select_chip_3();
+    spi_write( LS7366_CMD_LOAD_OTR );
+    deselect_chip_3();
+
+    select_chip_3();
+    spi_write( LS7366_CMD_READ_OTR );
+
+    uint32_t value = spi_read();
+    value = ( value << 8 ) | spi_read();
+    value = ( value << 8 ) | spi_read();
+    value = ( value << 8 ) | spi_read();
+
+    deselect_chip_3();
+
+    return value;
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_3 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_4 )
+
+uint32_t ls7366_read_counter_4()
+{
+    select_chip_4();
+    spi_write( LS7366_CMD_LOAD_OTR );
+    deselect_chip_4();
+
+    select_chip_4();
+    spi_write( LS7366_CMD_READ_OTR );
+
+    uint32_t value = spi_read();
+    value = ( value << 8 ) | spi_read();
+    value = ( value << 8 ) | spi_read();
+    value = ( value << 8 ) | spi_read();
+
+    deselect_chip_4();
+
+    return value;
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_4 )
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_1 )
+
+void ls7366_zero_counter_1()
+{
+    select_chip_1();
+    spi_write( LS7366_CMD_CLEAR_CNTR );
+    deselect_chip_1();
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_1 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_2 )
+
+void ls7366_zero_counter_2()
+{
+    select_chip_2();
+    spi_write( LS7366_CMD_CLEAR_CNTR );
+    deselect_chip_2();
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_2 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_3 )
+
+void ls7366_zero_counter_3()
+{
+    select_chip_3();
+    spi_write( LS7366_CMD_CLEAR_CNTR );
+    deselect_chip_3();
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_3 )
+
+#if defined( PRJ_LS7366_ENABLE_CHIP_4 )
+
+void ls7366_zero_counter_4()
+{
+    select_chip_4();
+    spi_write( LS7366_CMD_CLEAR_CNTR );
+    deselect_chip_4();
+}
+
+#endif // #if defined( PRJ_LS7366_ENABLE_CHIP_4 )
+
+// ----------------------------------------------------------------------------------------
+
+#if defined( PRJ_LS7366_INC_COMPUTE_DIFF )
+
+uint32_t ls7366_compute_diff( uint32_t first, uint32_t second, uint8_t* direction )
+{
+    //--    Compute the distance between the two values, where #1 is computed without
+    //      rollover compensation and #2 includes it.
+
+    uint32_t diff_1;
+    uint32_t diff_2;
+
+    if ( first < second )
+    {
+        diff_1 = second - first;
+        diff_2 = ( 0xffffffff - second ) + first + 1;
+    }
+    else
+    {
+        diff_1 = first - second;
+        diff_2 = ( 0xffffffff - first ) + second + 1;
+    }
+
+    //--    Return the smaller difference.
+    
+    if ( diff_1 < diff_2 )
+    {
+        *direction = ( first < second ? ls7366_counting_up : ls7366_counting_down );
+        return diff_1;
+    }
+    else
+    {
+        *direction = ( first > second ? ls7366_counting_up : ls7366_counting_down );
+        return diff_2;
+    }
+}
+
+#endif // #if defined( PRJ_LS7366_INC_COMPUTE_DIFF )
+
+// ----------------------------------------------------------------------------------------
+//  end of ls7366.cpp
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/packages/avr/sensors/ls7366/ls7366.h	Thu Dec 27 15:12:51 2012 -0800
@@ -0,0 +1,129 @@
+// ----------------------------------------------------------------------------------------
+//
+//  Copyright (C) 2012 Bob Cook
+//    
+//  Bob Cook Development, Robotics Library
+//  http://www.bobcookdev.com/rl/
+// 
+//  Control for the LSI LS7366 Quadrature Decoder / Counter
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+// 
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+// 
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+// ----------------------------------------------------------------------------------------
+
+#if !defined( BCDRL_AVR_SENSORS_LS7366_H )
+#define BCDRL_AVR_SENSORS_LS7366_H
+
+#include <stdint.h>
+
+// ----------------------------------------------------------------------------------------
+//  definitions from "project_defs.h"
+//
+//  enable LS7366 support with:
+//
+//      + PRJ_LS7366_ENABLE
+//
+//  enable individual LS7366 chips with:
+//
+//      + PRJ_LS7366_ENABLE_CHIP_# (where # is 1, 2, 3, or 4)
+//
+//  specify the SELECT pin for SPI communications for each chip with:
+//
+//      + PRJ_LS7366_SELECT_#_DDR
+//      + PRJ_LS7366_SELECT_#_PORT
+//      + PRJ_LS7366_SELECT_#_PIN
+//
+//  enable optional features with:
+//
+//      + PRJ_LS7366_INC_COMPUTE_DIFF
+//
+// ----------------------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------------------
+//  ls7366_init
+//
+//      Initialize the SPI bus and reset all enabled LS7366 chips.
+//
+
+void ls7366_init();
+
+// ----------------------------------------------------------------------------------------
+//  ls7366_reset_*
+//
+//      Reset the specified LS7366 chip to its power-on state.
+//
+//      Only compiled if the corresponding PRJ_LS7366_ENABLE_CHIP_# is defined.
+//
+
+void ls7366_reset_1();
+void ls7366_reset_2();
+void ls7366_reset_3();
+void ls7366_reset_4();
+
+// ----------------------------------------------------------------------------------------
+//  ls7366_read_counter_*
+//
+//      Return the specified LS7366 chip's counter value.
+//
+//      Only compiled if the corresponding PRJ_LS7366_ENABLE_CHIP_# is defined.
+//
+
+uint32_t ls7366_read_counter_1();
+uint32_t ls7366_read_counter_2();
+uint32_t ls7366_read_counter_3();
+uint32_t ls7366_read_counter_4();
+
+
+// ----------------------------------------------------------------------------------------
+//  ls7366_zero_counter_*
+//
+//      Reset the specified LS7366 chip's counter to zero.
+//
+//      Only compiled if the corresponding PRJ_LS7366_ENABLE_CHIP_# is defined.
+//
+
+void ls7366_zero_counter_1();
+void ls7366_zero_counter_2();
+void ls7366_zero_counter_3();
+void ls7366_zero_counter_4();
+
+
+// ----------------------------------------------------------------------------------------
+//  ls7366_compute_diff
+//
+//      Return the absolute difference between two encoder values. This function detects
+//      rollover events by assuming the maximum delta is never more than half the full
+//      encoder count (0xffffffff).
+//
+//      The count direction (counting up or down) is returned in the "direction" value.
+//
+//      The parameter "first" should be the initial sample, while "second" is the next
+//      sequential sample. In other words, "first" is older than "second" in time.
+//
+//      Only compiled if PRJ_LS7366_INC_COMPUTE_DIFF is defined.
+//
+
+const uint8_t ls7366_counting_up   = 0;
+const uint8_t ls7366_counting_down = 1;
+
+uint32_t ls7366_compute_diff( uint32_t first, uint32_t second, uint8_t* direction );
+
+
+#endif // #if !defined( BCDRL_AVR_SENSORS_LS7366_H )
+// ----------------------------------------------------------------------------------------