News:

Let's find out together what makes a PIC Tick!

Main Menu

I2COut does it really need 'Control?

Started by Ecoli-557, Mar 14, 2025, 07:54 PM

Previous topic - Next topic

Ecoli-557

Thanks to All, Pepe, I will add the 1us delay for good measure.
I now need to read back from a few registers to ensure they got written what I wanted!

Pepe

Delayus 1 can be replaced by some nop

Ecoli-557

#42
I am attempting to read back what I am writing to these registers as a way to ensure I am correct.
I have used Pepe's fragment to be this:
' Procedure to read from the WM8940
Proc ReadWM8940 (CODECReg As Byte) ,SPI_in as Word
    lOW CODEC_CS
    shOut SDA_Pin, SCL_Pin, 5, [CODECReg\8]
    High CODEC_CS
    delayus 1
    Low CODEC_CS
    SHIn SDA_Pin, SCL_Pin, 5, [SPI_in\16]
    high CODEC_CS
EndProc

and call it by this:
     ReadWM8940(CODEC_Pwr1)
     HSerOut ["PWR1 SPI_in=", hex4 SPI_in, " \n\r"]
     ReadWM8940(CODEC_DAC)
     HSerOut ["DAC SPI_in=", hex4 SPI_in, " \n\r"]
     readWM8940(CODEC_Clk)
     HSerOut ["CLK SPI_in=", hex4 SPI_in, " \n\r"]
     readWM8940(CODEC_AddlCntl)
     HSerOut ["AddlCntl SPI_in=", hex4 SPI_in, " \n\r"]
     readWM8940(CODEC_Pwr3)
     HSerOut ["Pwr3 SPI_in=", hex4 SPI_in, " \n\r"]

Using Mode 4, 5 and 7, I receive all I receive in SPI_In is 0xFFFF.
I am missing something quite simple.....

Ecoli-557

I just realized that I am looking at this all wrong.
According to the timing diagram:
3-wire timing.PNG
I STLL need to send the register address with the high-order 8-bit set.
Working on it .

Pepe

#44
The manual says that only registers 0, 1, and 32 can be read.

' Procedure to read from WM8940 using 3-wire protocol
Proc ReadWM8940(CODECReg As Byte), Word
    Dim ReadValue As Word
    CODECReg = (CODECReg & $7f) << 1
    Low CODEC_CS
    SHOut SDA_Pin, SCL_Pin, 5,[CODECReg] 
    SHIn SDA_Pin, SCL_Pin, 5,[ReadValue\16]
    High CODEC_CS
    Result = ReadValue
EndProc

Pepe

' Procedure to write WM8940 using 3-wire protocol
Proc WriteWM8940(CODECReg As Byte, Wdata As Word)
    CODECReg = ((CODECReg & $7F )<<1)| 1
    Low CODEC_CS
    SHOut SDA_Pin, SCL_Pin, 5,[CODECReg,Wdata]
    High CODEC_CS
EndProc

Ecoli-557

Quote from: Pepe on Mar 17, 2025, 07:02 PMThe manual says that only registers 0, 1, and 32 can be read.

Yes, I read that as well and thought it was curious why you cannot read back from a register you can write to.....
[quote
' Procedure to read from WM8940 using 3-wire protocol
Proc ReadWM8940(CODECReg As Byte), Word
    Dim ReadValue As Word
    CODECReg = (CODECReg & $7f) << 1
    Low CODEC_CS
    SHOut SDA_Pin, SCL_Pin, 5,[CODECReg] 
    SHIn SDA_Pin, SCL_Pin, 5,[ReadValue\16]
    High CODEC_CS
    Result = ReadValue
EndProc
[/quote]
I will use this Thanks Pepe, and 1st see what the 3 registers offer and then try others.
Curious little CODEC indeed.

Ecoli-557

Pepe- I must be missing from your example.  This is my code:
' Procedure to read from the WM8940 using 3-wire protocol
Proc ReadWM8940 (CODECReg As Byte) ,Word
    CODECReg = (CODECReg & 0x7f) << 1
    Low CODEC_CS
    SHOut SDA_Pin, SCL_Pin, 5,[CODECReg]
    SHIn SDA_Pin, SCL_Pin, 5, [SPI_in\16]
    high CODEC_CS
EndProc
And how I call it:
     ReadWM8940(CODEC_RST)                   'Should return Chip ID
     HSerOut ["RST SPI_in=", hex4 SPI_in, " \n\r"]
     ReadWM8940(CODEC_Pwr1)                  'Should return device revision
     HSerOut ["PWR1 SPI_in=", hex4 SPI_in, " \n\r"]
     ReadWM8940(CODEC_ALC1)                  'Should return ALC gain
On these and 3 others picked, all return 0xFFFF

tumbleweed

In order to read a register you need to set the msb of the address byte, not clear it and shift it left

Pepe

#49
Test this


Dim wdato as word

wdato= ReadWM8940(CODEC_RST)

HSerOut ["chip id =", dec wdato, " \n\r"]
Do
Loop

' Procedure to read from WM8940 using 3-wire protocol
Proc ReadWM8940(CODECReg As Byte), Word
    Dim ReadValue As Word
    CODECReg = CODECReg | $80
    Low CODEC_CS
    SHOut SDA_Pin, SCL_Pin, 5,[CODECReg]
    SHIn SDA_Pin, SCL_Pin, 7,[ReadValue\16]
    High CODEC_CS
    Result = ReadValue
EndProc

' Procedure to write WM8940 using 3-wire protocol
Proc WriteWM8940(CODECReg As Byte, Wdata As Word)
    CODECReg = CODECReg & $7F
    Low CODEC_CS
    SHOut SDA_Pin, SCL_Pin, 5,[CODECReg,Wdata\16]
    High CODEC_CS
EndProc

Ecoli-557

Thanks Tumbleweed and Pepe.
I will test this but it will need to wait about 4 days.
I have to be in Houston until Friday.
Regards to all,
Steve

Ecoli-557

I am back now, got back early.
Pepe:
This is the read proc:
' Procedure to read from WM8940 using 3-wire protocol
Proc ReadWM8940(CODECReg As Byte), Word
    Dim ReadValue As Word
    CODECReg = CODECReg | $80
    Low CODEC_CS
    SHOut SDA_Pin, SCL_Pin, 5,[CODECReg]
    SHIn SDA_Pin, SCL_Pin, 7,[ReadValue\16]
    High CODEC_CS
    Result = ReadValue
EndProc

And this is how I used it based on your input:

Dim wdato as word
wdato= ReadWM8940(CODEC_RST)
HSerOut ["chip id =", dec wdato, " \n\r"]

and this is what came back from Hserout:
[13:44:20 --- Rx] chip id =65535

I may go back and change the way I talking to the chip - perhaps start with a traditional I2C with the fixed address?

Pepe

Is CODECReg high when the codec is turned on? You can try removing | $80

Ecoli-557

Quote from: Pepe on Mar 20, 2025, 07:02 PMIs CODECReg high when the codec is turned on? You can try removing | $80
The CODEC chip sel is HIGH.  I did try '|0x80' in another attempt as you have to set the high-order 8-bit to READ from the register - it made no difference.
This is why I may try going back to the regular I2C communication structure and use the set address....... although the manual (not entirely clear) says you can use the Chip Select if you set the MODE pin HIGH - which I have.

Pepe


Ecoli-557

Quote from: Pepe on Mar 20, 2025, 07:11 PMTest Declare Shift_DelayUs = 1

My Decalars:
Device = 18F67K40
Declare Xtal = 64
On_Hardware_Interrupt GoTo My_IRQ
Declare Optimiser_Level = 0 'DISABLES the Optimiser
Declare I2C_Slow_Bus On     '64MHz may be too fast for the WM8940
Declare Shift_DelayUs = 1

AND, I noticed the register queried was incorrect, instead of CODEC_RST which is register '0x00' it should be register CODEC_Pwr1 which is register '0x01' which return the Device Revision.
Dim wdato as word
wdato= ReadWM8940(CODEC_PWR1)
HSerOut ["chip id =", dec wdato, " \n\r"]

Result:
[14:23:07 --- Rx] chip id =65535

Still not returning a correct reading I suspect.

Pepe

Test this
QuoteProc ReadWM8940(CODECReg As Byte), Word
    Dim ReadValue As Word
    Low CODEC_CS
    SHOut SDA_Pin, SCL_Pin, 5,[CODECReg]
    SHIn SDA_Pin, SCL_Pin, 7,[ReadValue\16]
    High CODEC_CS
    Result = ReadValue
EndProc

Pepe

 R0 Software Reset.   15:0 CHIP_ID
 R1 Power Management 1 2:0 DEVICE_REVISION

Ecoli-557

Quote from: Pepe on Mar 20, 2025, 07:29 PMTest this
QuoteProc ReadWM8940(CODECReg As Byte), Word
    Dim ReadValue As Word
    Low CODEC_CS
    SHOut SDA_Pin, SCL_Pin, 5,[CODECReg]
    SHIn SDA_Pin, SCL_Pin, 7,[ReadValue\16]
    High CODEC_CS
    Result = ReadValue
EndProc

Where do you equate the result from the Procedure to the query?
Dim wdato as word
wdato= ReadWM8940(CODEC_PWR1)
HSerOut ["chip id =", dec wdato, " \n\r"]

Ecoli-557

Quote from: Pepe on Mar 20, 2025, 07:33 PMR0 Software Reset.   15:0 CHIP_ID
 R1 Power Management 1 2:0 DEVICE_REVISION

Yes, I overlooked that