in this video I'd like to show you how you can write a simple iqu C driver to configure an audio codec if you're designing for example custom hardware and you need to do the bring up and test out if you can get audio in and out of your digital signal processing system in my particular case I have a custom PCB which we've seen in a number of previous videos which is specifically for guitar which uses an smm 3287 microcontroller as a DSP so this performs all of the digital signal processing tasks as as well as reads in for example control settings from adcs and switches and so on attached to this s 3287 microcontroller which is running as a DSP is an audio codec codec meaning it contains adcs and Dax so analog to digital converters and digital to analog converters and in this case this is an audio codec so these adcs and dac's are specifically tailored to audio frequencies and to audio bit depths in this case this is a Sirus logic CS 4270 which is a stereo input stereo output codec to 192 khz sampling frequency and up to 24 bits of bit depth quite good typical high-fi quality of course there are more parameters such as singles noise ratio total ammonic Distortion so on which characterize a codec but these are typical values you will see for audio codecs in this video we are specifically interested in configuring the codec using SM 3287 to set up for example sampling frequencies bit depths for example volumes and gains internal to the codec and just configuring this codec based on the data sheet data sheet registers and data sheet recommendations for this configuration link as we'll see there are often times various different ways of doing this but in this particular case of this board this is an I squ cink simply a data line and a clock line that are driven predominantly by the stim 287 and we can use those to then configure the codec i c in this case doesn't have anything to do with the actual audio data transfer which is achieved via additional i s lines so into integrated sound which is very typical for audio data and also has several clocks and we'll go through that in a bit of detail also in this video but again this is predominantly focused on the IED C register config for setting up an external codec the nice thing is once you've done this once for a particular codec once you need to do this for different codecs you will see that the setups are very very similar there similar types of registers you have to set up similar sequences you have to perform to then be able to stream data to and from the codec and a DSP if you're more interested in the iqu s of things and how to set that up with s32s and double buffering make sure to check out video number 55 on my channel which goes through exactly that setup for iqu S so I will assume a tiny bit of prerequisite knowledge and I strongly suggest you check out that video link will be in the description box below as usual a huge thank you to PCB way for sponsoring this video These Digital Signal processing effect boards for guitar I had manufactured and assembled by PCB way in China and they did a fantastic job for this I used their PCB protot type Service as well as their PCB assembly service make sure to check them out and I'll leave links to them in the description box below and at the time of making this video PB way also has their 10th anniversary and a couple cool tours and features on the website at the moment if you'd like to check that out again links in the description box below before we move over to writing the driver let's again just familiarize ourselves with the signals that are typically rooted out and into to a typical audio codec on the top right hand side I've taken a screenshot from the data sheet of the specific Cod that we're using in this example and we can see a typical pinout here in my particular case I'm using i s s to transfer audio data to and from the codec there are other means there are other means and interface standards as well but this is a very very generic and very popular interface the typical signals found in an i s interface are for example the ADC serial data and this is typically called sdn or sdti and per line so per Trace so to speak on your PCB this carries typically two channels of audio data from the codec back to the DSP the ADC data then we have Dax serial data very similar except the opposite direction this is typically called SD out or stto again two channels per line this time from the DSP to the codec i s s other than the serial data is a synchronous interface so we also have several clocks one is the word clock or left right clock or the frame sync signal and this word clock typically runs at the sampling rate FS so if you're running at 48 khz the word clock frequency will also be 4 8 khz typically and the word clock effectively tells us which channel we're currently looking at so if we're working with left and right channels if the word clock is low we are receiving or sending Left Channel data if the word clock is high we are receiving or transmitting right channel data an additional clock is the bit clock you'll of to see is B clock or s- clock and this typically runs at 64 times the sampling frequency and the bit clock is there to help the devices trigger on the centers of the serial data and we can see that on the bottom right hand side we have the left right clock or the word clock at the top the second clock is the bit clock at 64 frames per second and you can see the rising edges for example in this case should fall in the centers of our bits of the serial data that's both the ADC and the DAC data while not strictly part of the is s interface definition you often will find a Master Clock as part of these clock groupings and this Master Clock is synchronous with all of the other clocks but typically the phase of the Master Clock doesn't particularly matter and typically this Master Clock runs at 256 times the samply fre see now again all of these typical values are typical and there are different multiples depending on what sampling rates you're running at what speeds you're running at and so on and on the top right hand side of the codic we can see these iqu s signals so we have sdn left right clock M clock s clock and so on and that's typically what you'll find on iqu interface other than the iqu S signals we can typically run our codex in either Master mode or slave mode typically at least from what I've seen codex will be typically run in slave mode and the DSP will typically be in the master mode as we can see from a typical coded data sheet m slave mode effectively just determines which device is generating the clocks so if one device is in master mode that means it's generating the bit clock and the word clock whereas the slave mode device is receiving the word and the bit clock now not always the case but the mclog generation typically requires an external Crystal or Crystal oscillator in the case of using s732 H7 you can also use the internal RC oscillator to generate the iodes Master Clock however you will get less Jitter better performance and better accuracy by using a dedicated Crystal here just another slide to illustrate that these Master Clock Left Right clock and bit clock Left Right clock ratios aren't fixed so depending on our speed setting and the speed setting as we'll see determines if we can run for example at 48 khz or 90 khz or 192 khz sampling rates and we can have different ratios between all of these clocks other than the audio data which we have in this case via i s we of course have the codec configuration the configuration typically for codecs they might offer two modes that's either a software configuration or a hardware configuration and I've taken two images from the data sheet which we can see in the top right on the right hand side we have Standalone mode which is a hardware configuration so for example some of these pins for example pin 9 and pin 10 pin 11 and so on we either tie to a logic high or to a logic low to hardcode what mode we're running in for example what bit depth if we're running at i s or TDM or something else what sampling rate we can determine just by putting these pins high and low an alternative method and one I much refer is software mode configuration so now for the same device for example pins 9 and 10 can be used as an i squ c interface and for example pins 11 12 and 13 can be used to determine the address of this i s c slave and this is the mode I typically prefer and this is the mode we'll be using in this video to configure the device you can of course also have this in an SBI interface or three wire interface depends on the coding you're using other configuration signals might be a chip reset or power down signal which we should also hook up to the controlling device for example the DSP but we can use then these signals in software mode for example to set if we're in a master or slave mode we can set sampling rates clock ratios bit deps often times these codecs might include certain filters digital filters such as high pass filters low pass filters maybe volume or gain controls mud circuitry frame format slot sizes and much much more and we'll go through that for this particular codec typically you will do your configuration before you start your iquad s streams but keep in mind some codecs require for instance a master clock to be generated before we can do the configuration as some codecs do go into power down or sleep mode automatically if there's no clock signal applied again my suggestion is unless there is no specific serial interface available or you have limited IO I would strongly suggest to go with software mode for flexibility and for debugging capabilities the actual Hardware connections I have on this particular board are shown here this is a snippet of the codec schematic I have my serial audit interface in this case i s s connected to the i squ s lines of the codec I have an i squ c hooked up as well as a codec reset signal which is active low other than that I've tied the address pins via pull down resistors to ground to give a certain ice C address and we'll go through the codec data sheet in just a second and these connections will be very very similar across many different codex before we move over to the data sheet and then implementing this in C in software let's look at typical configuration steps that you'll pretty much always have to do anytime a codec is involved step number one is of course that once you P up your board the power rails come up and you would in most cases have a pull down resistor in place on the end reset or in power down lines if your codec has one to make sure the codec doesn't boot up by itself then your DSP or microcontroller whatever process you're using initializes we will configure the i s interface in the DSP or whatever interface you're using to transfer audio data and if necessary to start the isqu S clocks again this depends on the codec you're using for configuring isqu s that's to do with frame formats sampling rates bit depths how many channels you have after that we then configure the i squ c or the SPI interface whatever we're using to set up and configure the codec once all of this initial configuration is in place the DSP the processor then Cycles then reset all the power down pins to make sure we can then talk via a Serial interface i s c or SPI to the codec then we can perform the actual configuration of the codec quite simply the usual way we do this is we check the registers from the data sheet for example here the device we're using I've pasted in the register quick reference guide on the right hand side so we go through each one of these registers or or to minimum just the specific ones we need we'd read the codic registers toggle the bits depending on config and we have to watch out for some Reserve bits and we'll see this in just a second once we toggle the bits we write back this adjusted configuration to to that specific codic register and then finally we read back that written value just to verify that we actually wrote that value to that register again just like a double or triple check the order of configuration of course can be important for example some codecs require that it's actually powered down at least a software powered down before you make any changes for example to volume controls or isqu S configurations before you then power the device back up again so the order of configuration is something to keep in mind for any codec and this does in fact vary depending on what codec you're using after you've looped through and you set all the registers you power the codec up completely you can then begin running your processing Loop to process and retrieve and transmit your audio data and that's from that previous video video number 55 which goes through the I squs and dma streaming so now let's move over to the data sheet and s32 Cube IDE and look at how we can write such a simple driver let's briefly familiarize ourselves with the typical data sheet for one of these audio codecs the first page as us usual data sheets gives an overview of this codec this particular one is up to 24 bits bit depth up to 192 khz sampling rate and it's stereo we can read about the dynamic range Distortion and noise performances and what audio interface formats are available for example left Justified i squ s and right Justified it also includes for example a d emphasis filter pop CS volume controls high pass filters and more and this of course depends on what codec you're using but this is quite typical and quite a simple codec for us to explore if you go to the pin descriptions page four of the data sheet we see that we have a software mode pin description and a standalone or Hardware mode pin description as we saw in the slides earlier on and we're using software mode so that's why we'd have this first pin out then as usual typical connection diagrams and also descriptions of the various interface types we can use left Justified i s and more importantly for us we will be jumping to section five the applications section of this data sheet talking about Standalone mode and serial control Port mode what we're using is serial control Port mode or software mode and we can see section 5.2.1 already tells us quite a bit of information so that power up up achieve is by keeping the device in reset again with this pull down resistor which we saw until the supply pins are stable and then we release and reset so pull it high to power up this codec then after and reset is released or pulled High by our DSP in this case we actually have to set the power down bit to put this device into serial control port mode and if we don't do this within a certain number of sample periods after the release of reset the device enters this Standalone mode so this is something we have to keep in mind for the driver we have some more talk about Master Slave mode again who's generating the clocks then with regards to system clocking this particular device has three clock modes single speed double speed and quad speed and effectively this is just talking about the sing frequency so if we're running it typical audio sing frequencies we would be for example 44.1 khz or 48 khz and we would just stick with single speed mode otherwise if you want to go with 96 khz we'd have to go with double speed or 192 khz we'd have to go with quad speed depending on what suing frequency and sing rate you want you'll have to then also look at the clock ratio selection with single speed we have different Master Clock to Left Right clock ratios than we have double speed or quad speed whereas the bit clock to Left Right clock is always fixed at 64 and the left R clock itself is also fixed at the sampling rate we will come back to these tables because you can see on the right hand side we have these various setting bits M loock frequency 2 1 and zero which we have to also configure in the registers to put this device in single speed double speed or quad speed mode following on from this section we have more information on for example if you want to do digital loot backs muting using the highpass filter and so on so we will be referencing these sections once we go through these registers section six tells us more about software mode how for example the iqu C control works so for example the slave address is one o11 but this is followed by the address pin settings I've pulled all of my address setting pins low so it's 3 * 0 so we have an address of 1 011 followed by three zos we can see typical frame formats for iqu C or SPI if you'd like to use that instead now importantly for us what we're going to do is go through these registers and figure out what bits we do and we do not need to set codex will typically have a register quick reference which lists the address of the registers so we have 1 2 3 4 or out to 8 in this case so pretty simple device and what the bits in each register do so for example the first register at address hex1 gives us the device ID and the revision then for example the power control register at address hex2 gives us other bits such as the freeze and these other bits here as well as some reserved bits which have to be kept for example in this case at zero if you'd like to get more information on the individual registers and that's definitely something we'll need because we can't really guess what the freeze bit does just from this graph we can always scroll down or click on where the power control register is explained in more detail in this case page 32 and this tells us then about the individual functions of all these registers for example the freeze bit bit 7 has a description like so so in this case what we actually have to do is quite straight forward we have to make sure that we do a proper sequencing of these registers remember to go into software mode the data sheet tells us we have to write the power down control register bit and then we can start setting all these other registers but then we go through and set our default configurations for all these registers and afterwards we can then run our isqu s processing functions jumping over to stm32 cube IDE let's look at the basic configuration of this microcontroller if you've watched the i s s config video you'll be familiar with the SI settings and in this case I've set the protocol to be a i s standard protocol with a data size of 24 bits both for the adcs and for the Dax two channels and an audio frequency in this case only at 32 khz because this is this is for guitar effect pedal I don't need particularly much bandwidth we need to keep this in mind because we need to set the iqu S standard data size and audio frequency and we need to configure the codec correctly other than that for my configuration interface I just selected iqu C1 which is hooked up to the codec iquid sea lines the clock and data I'm just running in standard mode just 100 khz we're not doing at all much data transfer so we just use standard mode Let's go through the driver now and see how it's put together keep in mind this is a pretty simple driver it's part tailored to my needs of this guitar effect pedal there are certain things you could do to make it more modular and adaptive but this is the bare minimum to get one of these codecs going I've defined references to my i squ c handle so this was I squ C1 and references to where my gpio port is located for the reset signal then we have the ice C address and this was again defined in the data sheet which happens to then translate to hex 48 but the eighth bit is actually the read WR bit as is typical so we have to let left shift this address by one because the eighth bit again is used by the read right bit I've defined the various register addresses and that's simply taken from the register quick reference and we just have eight registers device ID all the way to the DC Channel B volume control 1 to8 so that's all I've transferred here I also have this device ID defined if we jump to register number one we'll need this just to verify that we're talking to this device correctly we can see bits 7 through 4 so the most significant four bits are equal to hex o C so therefore later we'll mask the whole register and check for that value what we'll actually be using to set the register configuration values all the default values is just an array where we have one value per register I have to find a reference to the iqu C handle and then we have our functions we have our main initialization function which will set up the codec Loop through the registers and set the values we want I've got a reset function which simply just toggles or Cycles the N reset pin and I've abstracted a tiny bit the hardware abstraction layer function so I have specific ones for this codec register right which is a single register WR function and a register read function which is a single register read jumping then over to the C file we have the codec reset function which effectively just toggles and reset pin so pulls it low Waits a certain amount of time pulls it high Waits a certain amount of time so we do this somewhat hard reset keep in mind you will typically need a delay specifically after you pull the device out of reset and power it up for the device to be ready and to be able to accept commands for example in software mode then I have my abstracted register WR and register read functions and for these I'm just essentially filling in the how iqu c m WR and how iqu c m read functions passing the iqu C handle the iqu C address what register address we want to talk to and then the registered data and that we want to read or write one bite essentially just a single bite write and a single bite read from the specific address using the register address we passed to this and either writing or reading a register data from or into that variable with that in place we can actually then look at the configuration function which is essentially this initialization function and always you should reference the data sheet of what the actual structure is how this needs to be configured in what order things need to configured how do you perform the resets how do you get this into software mode all of this is documented into the data sheet and while this is very similar across codex there are some minor differences between codex that means this approach might not and will probably not work for all so always make sure to follow the data sheet and their recommendations their recommendation was to do a hard reset of the codec using the end reset pin and then we want to put the codec in powerdown mode which puts this also in software mode as we saw when we were scanning through the data sheet so I'm writing a single register to the power and control register and setting certain values this is hex A3 and let's see why the power control register has these number of bits we have a frease bit reserved PDN EAC three Reserve bits PDN DAC and PDN to get get this into software mode we saw that we have to set the PDN bit High the rest doesn't really matter but I will enable the freeze bit and I will power down the adcs and I'll power down the Dax and I'll power down the entire system keep in mind for this particular power down we can St right to the registers of this device so in certain codecs when you to perform a power down you may not be able to write to the registers but in this case this does work so I'm going to set the freeze bit PDN ADC bit PDN DC bit and the PDN bit so in binary I've written that at the top we have wanted one then the reserve bits in this particular case as we saw from the register quick reference every time we have a reserved bit this needs to be zero and this might be different for the particular code that you're using you might have to check the state of the reserve bits and then do a bit mask instead rather than writing fixed values but in this case we can write fixed values of zero every time you have a reserved bit so therefore we want Freeze 1 reserved Z PDN ADC 1 0 0 0 1 1 so this is the binary value we have at the top left 1 0 1 0 0 0 1 1 that happens to be hex A3 and that's the value I used to put this codec in power down mode before we do any further steps then I check what this I C transfer function returns if it returns a timeout or busy or error then we jump out of this initialization function but now after the hard reset of the codec and putting the codec in power down mode we can now adjust the configuration and typically the first thing I will do is check the device ID the device ID we saw is actually register hex1 and we want the top four bits because those top four bits are fixed to be 11 whereas the lower four bits are the revision which might vary across device but we know that ID3 to ID Z are fixed so therefore I'd like to read that register so I do my register read function with the address of hex1 and I pass into that an 8bit wide variable which will then contain this register information so I perform register re Place information in the device ID and then I check the top four bits using this bit mask and to check if that the same as the device ID which is hex C which is 11 now that we've checked the device ID let's just verify that we're working so far that we perform the hard reset that we can put the codec in power down mode as suggested by the data sheet so we can actually put this in software mode and then we check the device ID so I'll set of breakpoint at line 35 and in main. C all I'm doing is I'm including my codec header file my codec driver and in int main after initialization of the serial audio interface the i squ s streams I'm initializing the codec with this call I've got an st link connected to my board and I've powered this up we've got a breakpoint set so I can click debug and now let's see if we reach that statement and let's see if we get the correct device ID out so we have a breakpoint straight from Main let me click resume okay we' landed the breakpoint we can check iqu C status by hovering that's hell K and let's check what device ID we've rid into this register and that's hex C3 remember we only interested in the upper four bits which is 11 which is hex C which is equal to our device ID so this is great this looks like it's working so far now we can actually move over to setting up the codec registers for setting up the codec registers remember we have eight registers here I've put in just a an array of bytes which have our desired values for these codic registers and again this is just following the order from the register quick reference so the first device ID then we have the power control mode control and so on and these values I filled in here I've calculated or set depending on what bits need to be set in these various registers we'll go through why we chose these certain registers in just a second but let me just go through how these are then actually written so we Loop through all of the registers and I'm actually starting at the last register hex8 and I'm looping down back to the power control register because the power control register is the last register I want to write to get this codec out of this low power State and power up the adcs remember the first thing we did was actually power down the device power down the adcs put this into this low power mode while we're adjusting the configuration so the last thing you want to do after we set the configuration is get it out of this low power mode so therefore I'm starting at the last register and moving through a loop back to the power control register the way I'm then doing that is writing to the current register index whatever the configuration settings were at that particular index then I'm reading back the register value just to confirm and if it's okay I Loop through to the next register value and after that we've actually configured our codec so what we need to do with this configuration is figure out what values we need to put into our default settings so let's go through these registers let's jump to the data sheet and look at mode control register number three and for this we have the first two bits are reserved then we have fm1 fm0 this Master Clock frequency settings and pop G and again the data sheet will explain everything fm1 fm0 determines the speed mode as well as if it's master or slave mode so if we're in master mode this will determine single double or quad speed but we are running this ceg and slave mode therefore the clocks will be generated by the DSP by the S 3287 and we want to select slave mode remember the reserve bits are zero so the first four bits are 0 0 1 1 two Reserve bits of zero and then fm1 is 1 and fm0 is one as well to put this into slave mode then we have three bits of clock frequency this is the ratio select bit and these are used to set the clocking ratios and the default is that all of these bits are zero which gives an M clock divide by one if we jump to the clock ratio selection section 5.2.4 we can see and scroll a bit down to slave mode we want to Def find our mclock frequency bits depending on if we're single speed double speed or quad speed I'm running this at 32 khz so I am in the single speed range my master clock generated by the sm32 H7 has a fixed ratio of 256 times the Left Right clock so therefore I want this first setting here so I want 0 0 0 for all these mclock frequency bits so therefore we can have three zeros and then we just need to set the last bit which is pop G so let's scroll down and that's a pop guard Trans in control control and we can read the description here and this sounds quite useful it helps reduce the effect of pops when we're turning on and off this device so we'll set the last bit at one so therefore we've got the register contents of 011 followed by three Z and 1 1 that gives us hex 31 and hex 31 is exactly what we have for this particular mode register it's in slave mode we have normal or single speed and we enable the pop card so that's why I have register value number 31 here and in this way we would go through the remaining registers in exactly the same methodology the next register is the ADC and d control and here we can able or disable the highp pass filters the digital loop back the digital audio interface format so in my case I don't want a highpass filter so I'll set the first two bits as zero I don't want a digital loot back so I'll set that to zero as well but I do want to set the DC digital interface format to be i s s because that's what I'm using in my case so I want bits zero and one for DAC diff 1 and DAC diff Z then we have two Reserve bits they have to be at zero and zero and then we have the ADC diff Z which is the digital interface format so we can choose between left Justified and i s s and I want i s s so I have a one there this gives me register contents in binary of four zeros followed by 1 0 0 1 and that in HEX aimal is hex 09 and that's exactly what I have here then I we continue that process for example for the transition control register for the mute control register and the volume control registers very very similar process figuring out what bits I need to set and which I don't need to set watching out for Reserve bits and writing them to the registers and then reading them back just to verify now of course you don't have to do a single register read and register WR you could do a block based read and block based right it depends on how you set up your driver keep in mind this is a very very simple driver so what I could do let me just set a breakpoint line 61 let's upload this code and debug and just check that all the register contents are as they should be and that they're being written to and read correctly then I click resume and we want to make sure that Reg data that's being read back is the same as our configuration data so we want to make sure this Top Value equals the bottom value for all the red registers so we're Reading Writing and making sure that all the registers are coming back and hopefully with everything read back and configured correctly we can return zero and end our initialization function and click resume and now the codic is correctly configured and we're running our main processing Loop so I can set a breakpoint in the process half buffer function and we can see our codec is being configured because we're getting input data and setting output data if you'd like to see this codec driver in action you can see this across various different videos on my channel for example the previous video on realtime frr filters uses that driver or when we're doing a QA 43 audio analyzer tutorial looking at noise snrs total harmonic Distortion and so on that's using that driver for example the impulse responses so this driver has been utilized on many many different systems and make sure to check those out this driver of course is very very simple it covers the absolute Basics if you'd like to see a more extended driver in the Linux repo they actually have a driver for this particular part and you can see how for example a professional driver is written with all of the defines and bit masking if you want to make this driver far far more flexible rather than just having one for example standard configuration I'd strongly suggest checking this out and I'll leave a link to this in the description box below in any case I hope this video was helpful I hope it showed you how you can quite easily interface with codex and configure them just by going through the data sheet and paying attention to the register setup if you like the video please leave a like a comment if you have any questions and don't forget to subscribe to stay up to date to any latest firmware DSP Hardware design and PCB design videos thanks again for watching and I hope to see you in the next one bye-bye