Main Site Documentation

Raspberry PI 3 + PulseCount 1.1


#1

Hi, I am trying to use GHI Pulse Count Module with Windows 10 IoT. Unfortunately, I am not able to configure the module. Can you give me a hint please? I am begginer. My code looks like this:


static class LS7366
    {
        /*******************************************************************
    // LS7366 REGISTERS
    //------------------------------------------------------------------
    // MDR0 : MoDe Register 0 (8 bit read/write)
    //        Upon power up, MDR0 is set to zero
    //        B1 B0: count mode 1
    //            00 = non quadrature mode (A = clock, B = direction)
    //            01 = x1 quadrature mode (one count per quad. cycle)
    //            10 = x2 quadrature mode (two counts per quad. cycle)
    //            11 = x4 quadrature mode (four counts per quad. cycle)
    //        B3 B2: count mode 2
    //            00 = free running count mode
    //            01 = single-cycle count mode (disabled on carry or
    //                 borrow, resumed on reset)
    //            10 = range limit count mode (up and down between DTR
    //                 and zero, freezes at limit and resumes on 
    //                 direction change
    //            11 = modulo-n count, where n = DTR in both directions
    //        B5 B4: index function
    //            00 = 
    //            01 =
    //            10 =
    //            11 =
    //        B6:  0 = asynchronous index
    //             1 = synchronous index (overriden in non-quad. mode)
    //        B7:  0 = filter clock division factor = 1
    //             1 = filter clock division factor = 2
    //------------------------------------------------------------------
    // MDR1 : MoDe Register 1 (8 bit read/write) as appendix to MDR0
    //        Upon power up, MDR0 is set to zero
    //        B1 B0: count mode 1
    //            00 = 4-byte counter mode
    //            01 = 3-byte counter mode
    //            10 = 2-byte counter mode
    //            11 = 1-byte counter mode
    //        B2:  0 = enable counting
    //             1 = disable counting
    //        B3:  not used
    //        B4:  0 = NOP
    //             1 = FLAG on IDX (B4 of STR) \
    //        B5:  0 = NOP                      |
    //             1 = FLAG on CMP (B5 of STR)  |  NOTE: applicable on
    //        B6:  0 = NOP                       > both LFLAG and DFLAG
    //             1 = FLAG on BW (B6 of STR)   |
    //        B7:  0 = NOP                      |
    //             1 = FLAG on CY (B7 of STR)  /
    //------------------------------------------------------------------
    // DTR  : DaTa Register input (8, 16, 24 or 32 bits)
    //        Can be written directly from MOSI
    //------------------------------------------------------------------
    // CNTR : CouNTer Register (8, 16, 24 or 32 bits)
    //        This register counts the up/down pulses from the quad.
    //        clock applied at the A and B inputs or alternatively
    //        from the A input in non-quad. mode
    //------------------------------------------------------------------
    // OTR  : OuTput Register (8, 16, 24 or 32 bits)
    //        Shadow register from CNTR to read the counter value
    //        during counting. Can be read directly from MOSI while
    //        the counter still counts
    //------------------------------------------------------------------
    // STR  : STatus Register (8 bit read)
    //        B0: S   = signbit (0 neg, 1 pos)
    //        B1: U/D = up/down indicator (0 down, 1 up)
    //        B2: PLS = power loss indicator latch; set upon powerup
    //        B3: CEN = count enable status (0 disabled, 1 enabled)
    //        B4: IDX = index latch
    //        B5: CMP = compare (CNTR = DTR) latch
    //        B6: BW  = borrow (CNTR underlow) latch
    //        B7: CY  = carry (CNTR overflow) latch
    //------------------------------------------------------------------
    // IR   : Instruction Register (8 bit write)
    //        B2 B1 B0 : XXX (don't care)
    //        B5 B4 B3 : 000 = select none
    //                   001 = select MDR0
    //                   010 = select MDR1
    //                   011 = select DTR
    //                   100 = select CNTR
    //                   101 = select OTR
    //                   110 = select STR
    //                   111 = select none
    //           B7 B6 :  00 = CLR register
    //                    01 = RD register
    //                    10 = WR register
    //                    11 = LOAD register
    /*******************************************************************
    // Number of Bytes | OP Code | Register |  Operation
    //-----------------+---------+----------+---------------------------
    //                 |         | MDR0     | Clear MDR0 to zero
    //                 |         | MDR1     | Clear MDR1 to zero
    //       1         |  CLR    | DTR      | None
    //                 |         | CNTR     | Clear CNTR to zero
    //                 |         | OTR      | None
    //                 |         | STR      | Clear STR to zero
    //-----------------+---------+----------+---------------------------             
    //                 |         | MDR0     | Output MDR0 on MISO
    //                 |         | MDR1     | Output MDR1 on MISO
    //    2 to 5       |  RD     | DTR      | None
    //                 |         | CNTR     | Transfer CNTR to OTR, 
    //                 |         |          | then output OTR on MISO
    //                 |         | OTR      | Output OTR on MISO
    //                 |         | STR      | Output STR on MISO
    //-----------------+---------+----------+---------------------------
    //                 |         | MDR0     | Write at MOSI into MDR0
    //                 |         | MDR1     | Write at MOSI into MDR1
    //    2 to 5       |  WR     | DTR      | Write at MOSI into DTR
    //                 |         | CNTR     | None
    //                 |         | OTR      | None
    //                 |         | STR      | None
    //-----------------+---------+----------+---------------------------
    //                 |         | MDR0     | None
    //                 |         | MDR1     | None
    //       1         |  LOAD   | DTR      | None
    //                 |         | CNTR     | Transfer DTR to CNTR
    //                 |         | OTR      | Transfer CNTR to OTR
    *******************************************************************/


        #region Registers, commands and modes

        // LS7366 Commands
        public enum Commands : byte
        {
            LS7366_CLEAR = 0x00, // clear register
            LS7366_READ = 0x40, // read register
            LS7366_WRITE = 0x80, // write register
            LS7366_LOAD = 0xC0, // load register
        }

        // LS7366 Registers
        public enum Registers : byte
        {
            LS7366_MDR0 = 0x08, // select MDR0
            LS7366_MDR1 = 0x10, // select MDR1
            LS7366_DTR = 0x18, // select DTR
            LS7366_CNTR = 0x20, // select CNTR
            LS7366_OTR = 0x28, // select OTR
            LS7366_STR = 0x30, // select STR
        }

        // LS7366 MDR0 Counter modes
        public enum MDR0Mode : byte
        {
            LS7366_MDR0_QUAD0 = 0x00, // none quadrature mode
            LS7366_MDR0_QUAD1 = 0x01, // quadrature x1 mode
            LS7366_MDR0_QUAD2 = 0x02, // quadrature x2 mode
            LS7366_MDR0_QUAD4 = 0x03, // quadrature x4 mode
            LS7366_MDR0_FREER = 0x00, // free run mode
            LS7366_MDR0_SICYC = 0x04, // single cycle count mode
            LS7366_MDR0_RANGE = 0x08, // range limit count mode (0-DTR-0)
                                      // counting freezes at limits but 
                                      // resumes on direction reverse
            LS7366_MDR0_MODTR = 0x0C, // modulo-n count (n=DTR both dirs)
            LS7366_MDR0_DIDX  = 0x00, // disable index
            LS7366_MDR0_LDCNT = 0x10, // config IDX as load DTR to CNTR
            LS7366_MDR0_RECNT = 0x20, // config IDX as reset CNTR (=0)
            LS7366_MDR0_LDOTR = 0x30, // config IDX as load CNTR to OTR  
            LS7366_MDR0_ASIDX = 0x00, // asynchronous index
            LS7366_MDR0_SYINX = 0x40, // synchronous IDX (if !NQUAD)
            LS7366_MDR0_FFAC1 = 0x00, // filter clock division factor=1
            LS7366_MDR0_FFAC2 = 0x80, // filter clock division factor=2
            LS7366_MDR0_NOFLA = 0x00, // no flags
        }

        // LS7366 MDR1 counter modes
        public enum MDR1Mode : byte
        {
            LS7366_MDR1_4BYTE = 0x00, // 4 byte counter mode
            LS7366_MDR1_3BYTE = 0x01, // 3 byte counter mode
            LS7366_MDR1_2BYTE = 0x02, // 2 byte counter mode
            LS7366_MDR1_1BYTE = 0x03, // 1 byte counter mode
            LS7366_MDR1_ENCNT = 0x00, // enable counting
            LS7366_MDR1_DICNT = 0x04, // disable counting
            LS7366_MDR1_FLIDX = 0x20, // FLAG on IDX (index)
            LS7366_MDR1_FLCMP = 0x40, // FLAG on CMP (compare)
            LS7366_MDR1_FLCY = 0x80, // FLAG on CY (carry)
        }
        #endregion Registers, commands and modes
    }


//Pulse Counter (GHI)
        private async void InitPulseCounter()
        {
            const string SPI_CONTROLLER_NAME = "SPI0";
            const Int32 SPI_CHIP_SELECT_LINE = 0;


            var settings = new SpiConnectionSettings(SPI_CHIP_SELECT_LINE);
            settings.ClockFrequency = 4000000;
            settings.Mode = SpiMode.Mode3;


            string spis = SpiDevice.GetDeviceSelector(SPI_CONTROLLER_NAME);
            var dis = await DeviceInformation.FindAllAsync(spis);
            this.spiPulseCounter = await SpiDevice.FromIdAsync(dis[0].Id, settings);
            if (spiPulseCounter == null)
            {
                System.Diagnostics.Debug.WriteLine(
                    "SPI Controller is currently in use by " +
                    "another application. Please ensure that no other applications are using SPI.");
            }

            #region Clear registers

            // Clear MDR0 register
            this.spiPulseCounter.Write(new byte[] { (byte)LS7366.Commands.LS7366_CLEAR | (byte)LS7366.Registers.LS7366_MDR0 });
            // Clear MDR1 register
            this.spiPulseCounter.Write(new byte[] { (byte)LS7366.Commands.LS7366_CLEAR | (byte)LS7366.Registers.LS7366_MDR1 });
            // Clear STR register
            this.spiPulseCounter.Write(new byte[] { (byte)LS7366.Commands.LS7366_CLEAR | (byte)LS7366.Registers.LS7366_STR });
            // Clear CNTR
            this.spiPulseCounter.Write(new byte[] { (byte)LS7366.Commands.LS7366_CLEAR | (byte)LS7366.Registers.LS7366_CNTR });
            // Clear ORT (write CNTR into OTR)
            this.spiPulseCounter.Write(new byte[] { (byte)LS7366.Commands.LS7366_LOAD | (byte)LS7366.Registers.LS7366_OTR });
            #endregion

            #region Configure MDR0 and MDR1 registers

            // Configure MDR0 register
            this.spiPulseCounter.Write(new byte[2] { (byte)LS7366.Commands.LS7366_WRITE     // write command
                             | (byte)LS7366.Registers.LS7366_MDR0,                          // to MDR0
                               (byte)LS7366.MDR0Mode.LS7366_MDR0_QUAD0                      // none quadrature mode
                             | (byte)LS7366.MDR0Mode.LS7366_MDR0_MODTR                      // modulo-n counting 
                             | (byte)LS7366.MDR0Mode.LS7366_MDR0_DIDX });                   // disable index 

            // Configure MDR1 register
            this.spiPulseCounter.Write(new byte[2] { (byte)LS7366.Commands.LS7366_WRITE     // write command
                             | (byte)LS7366.Registers.LS7366_MDR1,                          // to MDR1
                               (byte)LS7366.MDR1Mode.LS7366_MDR1_4BYTE                      // 4 byte counter mode
                             | (byte)LS7366.MDR1Mode.LS7366_MDR1_ENCNT                      // enable counting
                             /* | (byte)LS7366.MDR1Mode.LS7366_MDR1_FLCMP */  });           // FLAG on CMP (compare) 

            #endregion

            #region Read registers to test

            // Read/write buffers
            byte[] LS7366_2B_rd = new byte[2]; // read two bytes
            byte[] LS7366_4B_rd = new byte[4]; // read four bytes

            // Read MDR0 register
            this.spiPulseCounter.TransferFullDuplex(new byte[2] { (byte)LS7366.Commands.LS7366_READ    // read
                                            | (byte)LS7366.Registers.LS7366_MDR0, 0 }, LS7366_2B_rd);    // MDR0

            System.Diagnostics.Debug.WriteLine($" B0={LS7366_2B_rd[0]}, B1={LS7366_2B_rd[1]}");

            // Read MDR1 register
            this.spiPulseCounter.TransferFullDuplex(new byte[2] { (byte)LS7366.Commands.LS7366_READ    // read
                                            | (byte)LS7366.Registers.LS7366_MDR1, 0 }, LS7366_2B_rd);    // MDR1

            System.Diagnostics.Debug.WriteLine($" B0={LS7366_2B_rd[0]}, B1={LS7366_2B_rd[1]}");

            // Read STR register
            this.spiPulseCounter.TransferFullDuplex(new byte[2] { (byte)LS7366.Commands.LS7366_READ    // read
                                            | (byte)LS7366.Registers.LS7366_STR, 0 }, LS7366_2B_rd);    // MDR1

            System.Diagnostics.Debug.WriteLine($" B0={LS7366_2B_rd[0]}, B1={LS7366_2B_rd[1]}");

            #endregion


        }

Thank you!


#2

OK, here is the working code:

//Pulse Counter (GHI)
        private async Task InitPulseCounter()
        {
            const string SPI_CONTROLLER_NAME = "SPI0";
            const Int32 SPI_CHIP_SELECT_LINE = 0;


            var settings = new SpiConnectionSettings(SPI_CHIP_SELECT_LINE);
            settings.ClockFrequency = 12000000;
            settings.Mode = SpiMode.Mode0;


            string spis = SpiDevice.GetDeviceSelector(SPI_CONTROLLER_NAME);
            var dis = await DeviceInformation.FindAllAsync(spis);
            this.spiPulseCounter = await SpiDevice.FromIdAsync(dis[0].Id, settings);
            if (spiPulseCounter == null)
            {
                System.Diagnostics.Debug.WriteLine(
                    "SPI Controller is currently in use by " +
                    "another application. Please ensure that no other applications are using SPI.");
            }


            #region Clear registers

            // Clear MDR0 register
            this.spiPulseCounter.Write(new byte[] { (byte)LS7366.Commands.LS7366_CLEAR | (byte)LS7366.Registers.LS7366_MDR0 });
            // Clear MDR1 register
            this.spiPulseCounter.Write(new byte[] { (byte)LS7366.Commands.LS7366_CLEAR | (byte)LS7366.Registers.LS7366_MDR1 });
            // Clear STR register
            this.spiPulseCounter.Write(new byte[] { (byte)LS7366.Commands.LS7366_CLEAR | (byte)LS7366.Registers.LS7366_STR });
            // Clear CNTR
            this.spiPulseCounter.Write(new byte[] { (byte)LS7366.Commands.LS7366_CLEAR | (byte)LS7366.Registers.LS7366_CNTR });
            // Clear ORT (write CNTR into OTR)
            this.spiPulseCounter.Write(new byte[] { (byte)LS7366.Commands.LS7366_LOAD | (byte)LS7366.Registers.LS7366_OTR });
            #endregion

            #region Configure MDR0 and MDR1 registers

            // Configure MDR1 register
            this.spiPulseCounter.Write(new byte[2] { (byte)LS7366.Commands.LS7366_WRITE     // write command
                             | (byte)LS7366.Registers.LS7366_MDR1,                          // to MDR1
                               (byte)LS7366.MDR1Mode.LS7366_MDR1_4BYTE                      // 4 byte counter mode
                             | (byte)LS7366.MDR1Mode.LS7366_MDR1_ENCNT                      // enable counting
                             | (byte)LS7366.MDR1Mode.LS7366_MDR1_FLCMP });           // FLAG on CMP (compare) 

            #endregion

            #region Read registers to test

            // Read buffer
            byte[] LS7366_2B_rd = new byte[2]; // read two bytes

            // Read MDR0 register
            this.spiPulseCounter.TransferFullDuplex(new byte[2] { (byte)LS7366.Commands.LS7366_READ    // read
                                            | (byte)LS7366.Registers.LS7366_MDR0, 0 }, LS7366_2B_rd);    // MDR0

            System.Diagnostics.Debug.WriteLine($" B1={LS7366_2B_rd[1]}");

            // Read MDR1 register
            this.spiPulseCounter.TransferFullDuplex(new byte[2] { (byte)LS7366.Commands.LS7366_READ    // read
                                            | (byte)LS7366.Registers.LS7366_MDR1, 0 }, LS7366_2B_rd);    // MDR1

            System.Diagnostics.Debug.WriteLine($" B1={LS7366_2B_rd[1]}");

            // Read STR register
            this.spiPulseCounter.TransferFullDuplex(new byte[2] { (byte)LS7366.Commands.LS7366_READ    // read
                                            | (byte)LS7366.Registers.LS7366_STR, 0 }, LS7366_2B_rd);    // STR

            System.Diagnostics.Debug.WriteLine($" B1={LS7366_2B_rd[1]}");

            #endregion


        }