Official Blog of Silicon Labs

    Publish
     
      • High Quality Audio with I2S - Part 2

        lynchtron | 10/300/2016 | 11:36 AM

        13_title.png

        In the last section, I introduced the CS4344 I2S audio device and covered the basics of digital audio, including how sample rate is determined and how that rate relates to the sample rate clock in MCLK.  We should have the I2S device ready to go but now we need to fetch some audio files to feed into it.  In this section, we will connect the MicroSD card to the Starter Kit and verify that the sound files can be opened and that the type of file is correct, before finally playing the audio file over a pair of headphones.

         

        Connecting the MicroSD and I2S DAC Hardware

        In order to connect the MicroSD card that is utilized by the DK3850_wavplayer example, I had to figure out where the example was setting up its GPIOs for it.  I didn’t see them in the main file or any of the files in the src directory.  I started tracing through the code, found the MicroSD_Init function, right-clicked on that, and then opened its declaration.  The microsd.h file didn’t give me the information that I wanted to know, but I noticed that it included a microsdconfig.h file, so I opened the declaration for that and found the information I needed:

         

        #define MICROSD_USART           USART0
        #define MICROSD_LOC             USART_ROUTE_LOCATION_LOC1
        #define MICROSD_CMUCLOCK        cmuClock_USART0
        #define MICROSD_GPIOPORT        gpioPortE
        #define MICROSD_MOSIPIN         7
        #define MICROSD_MISOPIN         6
        #define MICROSD_CSPIN           4
        #define MICROSD_CLKPIN          5

        But this was a problem because pins PE4, PE5, PE6 and PE7 are not brought out on the Wonder Gecko Starter Kit.  This wavplayer example was developed for the Development Kit.  So I scoured the Datasheet and Starter Kit User Guide for available USART pins and found PC3, PC4, and PC5 on the expansion header on the side of the board and PC2 on the lower side of the board breakout.  These were on USART2 location 0.  All I needed to do was copy the microsdconfig.h file into my Drivers folder (right next to the microsd.c file), and update it so I had the MicroSD card installed in the right place.

         

        #define MICROSD_USART           USART2
        #define MICROSD_LOC             USART_ROUTE_LOCATION_LOC0
        #define MICROSD_CMUCLOCK        cmuClock_USART2
        #define MICROSD_GPIOPORT        gpioPortC
        #define MICROSD_MOSIPIN         2
        #define MICROSD_MISOPIN         3
        #define MICROSD_CSPIN           5
        #define MICROSD_CLKPIN          4

         

        Connect the MicroSD card reader to the Starter Kit as follows:

         13_connections.png


         

        Starter Kit                                                      MicroSD Card Breakout

        V3_3                                                               VCC

        GND                                                                GND

        PC2 – US2_TX, Location 0                           DI

        PC3 – US2_RX, Location 0                          DO

        PC4 – US2_CLK, location 0                         SCK

        PC5 – US2_CS, Location 0                           CS

         

        Once the MicroSD card is connected, we can turn our attention to the I2S breakout board.  This one is more straightforward because the connections are listed right in the wavplayer.c file:

         

          GPIO_PinModeSet(gpioPortD, 0, gpioModePushPull, 0);
          GPIO_PinModeSet(gpioPortD, 2, gpioModePushPull, 0);
          GPIO_PinModeSet(gpioPortD, 3, gpioModePushPull, 0);

        Those pins are readily available on the top side of the Starter Kit, so we don’t need to make any modifications.  In addition to the I2S signals from the wavplayer.c file, we also need to connect the MCLK to a pin that is capable of a timer output.  I selected PD7 for this purpose.  Connect the PmodI2s board as follows:

        13_i2s_breakout.png

        Starter Kit                                                      PmodI2S Board

        PD7 – Timer 1 Capture Channel                Pin 1 – MCLK

        PD3 – US1_CS, Location 1                          Pin 2 – LRCK

        PD2 - US1_CLK, Location 1                         Pin 3 - SCLK

        PD0 - US1_TX, Location 1                           Pin 4 - SDIN

        GND                                                                Pin 5 - GND

        V3_3                                                               Pin 6 - VCC


        Next, prepare the MicroSD card.  You need an SD slot on your computer or a USB adapter for SD.   Copy the sweet1.wav file from the github repo onto your MicroSD card using the SD card adapter.   Make sure that your card is formatted as FAT32, which should be the way that it is shipped to you.  

         13_sd_card.png

         

        The MicroSD and I2S Software

        The wavplayer.c file is a long file, so I can’t just paste the whole thing here.  Instead I will pull out key sections and explain them.  You can follow along by downloading the modified wavplayer.c source from github.

         

        When I made the changes mentioned above, compiled my files, and ran the debugger, nothing happened, which is very usual whenever I try something for the first time!  I had to hit the pause button in Simplicity Studio to see where it was stuck.  It was sitting at a while loop in the wavplayer.c file that was reserved for error conditions:

         

            /* No micro-SD with FAT32 is present */
            while (1) ;

        I tried reseating the MicroSD card and this time I set a breakpoint just after the line in main() that reads the header for the .wav file:

         

        /* Read header and place in header struct */
          f_read(&WAVfile, &wavHeader, sizeof(wavHeader), &bytes_read);

        When I hit the reset button in Simplicity Studio and hit play again, this time the debugger broke just after that line, and I was able to hover my mouse on the wavHeader variable and examine the contents, which proved that I finally was able to read the .wav file:

         13_proof_of_riff.png


        If you see the “RIFF…” in the first part, you know that you have succeeded, because that is part of the WAV file specification.  But you can also examine the rest of the header file there including total number of bytes, number of channels (mono or stereo) sample frequency, etc.  It’s all there.

         

        As it turns out, I was able to read a file from my Micro SD card without writing any code!  That’s great, but if you take a look at the code to see what it is doing, it is calling the MicroSD_Init function which configures the GPIOs and the USART for SPI operation.  Then, the wavplayer.c file calls upon the FatFS library’s f_mount function, which is included in the file with ff.h.  Once again, a library did all of the heavy lifting, in this case deciphering the FAT file system over the MicroSD SPI interface.

         

        If you peek into the ff.c file, you can see exactly what it is doing.  Here is the FatFS libraries f_mount function:

         

        /*-----------------------------------------------------------------------*/
        /* Mount/Unmount a Logical Drive                                         */
        /*-----------------------------------------------------------------------*/
         
        FRESULT f_mount (
              BYTE vol,         /* Logical drive number to be mounted/unmounted */
              FATFS *fs         /* Pointer to new file system object (NULL for unmount)*/
        )
        {
              FATFS *rfs;
         
         
              if (vol >= _VOLUMES)          /* Check if the drive number is valid */
                    return FR_INVALID_DRIVE;
              rfs = FatFs[vol];             /* Get current fs object */
         
              if (rfs) {
        #if _FS_SHARE
                    clear_lock(rfs);
        #endif
        #if _FS_REENTRANT                   /* Discard sync object of the current volume */
                    if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR;
        #endif
                    rfs->fs_type = 0;       /* Clear old fs object */
              }
         
              if (fs) {
                    fs->fs_type = 0;        /* Clear new fs object */
        #if _FS_REENTRANT                   /* Create sync object for the new volume */
                    if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR;
        #endif
              }
              else /* Unmount, Added by Energy Micro AS. */
              {
                disk_ioctl(fs->drv, CTRL_INVALIDATE, (void*)0);
              }
              FatFs[vol] = fs;              /* Register new fs object */
         
              return FR_OK;
        }

        Yikes!  That is not very clear to me.  But if you look at it long enough, you can probably figure it out.  I prefer longer, more descriptive variable names than the short-hand code used in this library.  The size of your variable names don’t impact the code size running in the MCU, so don’t skimp on them.   In addition, the FatFS library uses a lot of single-line conditional statements without curly braces, and mixes those within the same block of code.  This can lead to errors when new lines are added without paying careful attention.  For example, this block of code is clear:

         

        if (foo)
              x =1
        if (bar)
              y = 1

        However, if you were to add a statement to the first block, it might look clear when you write it, but the indentation means nothing to the C compiler unlike the scripting language Python.  Later, you may want to add a statement here, but the following:

         

        if (foo)
              x = 1;
              z = 1;
        if (bar)
              y = 1;

        Has the same meaning as the following:

         

        if (foo)
              x = 1;
        z = 1;
        if (bar)
              y = 1;

        That is why I find it is better to always use the curly braces unless it is a very special case, and then keep it consistent over that entire block of code.  Don’t mix the use of curly braces and the lack of curly braces in the same area of code.

         

        We can single-step through these external libraries as we do with our own code, but whenever I use standard libraries such as this one, I try to avoid looking into the functions too much.  It is better in my experience to simply read information about them from their official sources or in discussion forums online.  If I find a problem in a widely-used library like this one, the problem is probably my fault. 
         
        Once I had the MicroSD card loading, I hit play again and the chip produced sound, but it was cutting off the beginning of the file.  Further examination of the spec revealed why that was happening.  In order to avoid pops in the audio, the CS4344 delays any audio for about 2000 samples after data starts to stream to the chip.  This meant that I had to find a way to generate 2000 dummy clock edges (LRCLK) and then reset the file pointer in the FatFS to point back to the beginning of the file. 

        13_power_up.jpg

         

        Here is the code that I used to do reset the LRCLK after some time. I placed this code in the FillBufferFromSDcard function, and I had to experiment with the FUDGE factor to get it right, since the CS4344 spec wasn’t specific in how long it took for the part to wake up from power down mode.

         

        #define FUDGE 9000
          static bool need_to_rewind = true;
          if (need_to_rewind && ByteCounter > FUDGE)
          {
                f_lseek(&WAVfile, f_tell(&WAVfile) - FUDGE);
                need_to_rewind = false;
                ByteCounter -= FUDGE;
          }

        Now, when I recompiled and hit the play button, I was able to hear the full sound clip.

         

        You can see all of the changes that I needed to make to my wavplayer.c in the github repo and examine any differences from an unmodified version of wavplayer.c.  You can get an original copy of wavplayer.c by using the Software Examples tile in Simplicity Studio, selecting the Wonder Gecko 3850 Development Kit, then Next, then pick the DK3850_wavplayer example, and finish importing that into your workspace.  Navigate to its src directory and open the wavplayer.c file.

         

        In order to easily compare differences across files, download WinMerge and compare the wavplayer.c file in the example that you just imported versus the wavplayer.c file version in this chapter's github repo.  WinMerge will highlight all changes between the two files side-by-side, and you can see a visual indication of all of the changes on the left-hand side “Location Pane.”  By clicking the “Next Difference” arrow, you can look at all of the changes.

         
        Here is what WinMerge displays when I examine the “fudge fix” above:

        13_diff_tool.png

         

        Another thing that was nice about this example was that I didn’t have to set up the DMA tables for the Ping Pong data transfer.  The example already configured that properly.  We will learn more about the DMA and I2S setup later in this chapter.

         

        In the next section, we will rewrite the I2S driver to better match our needs, and figure out what the DMA peripheral is doing in this example.

         

         PREVIOUS | NEXT

      • Inboard Technology Uses Connectivity to Bring Style and Speed to Personal Transportation

        deirdrewalsh | 10/299/2016 | 12:06 PM

         inboard-quote.png

         

        Inboard Technology recently unveiled its M1 Electric Skateboard, which sets itself apart from similar products by focusing on style, functionality, and connectivity. You read that right – this is an IoT skateboard, and it has the potential change the way people look at transportation. We recently had the opportunity to speak with Inboard’s co-founder and CEO, Ryan Evans. He shared with us the inspiration for the M1 and how the team went from idea to finished product.

         

        Explain a little bit about Inboard. What was the genesis of the company?

        Everyone’s been in the situation, whether walking on a college campus or a mall, or a live music event, when you just want a ride. My friend Theo (Theo Cerboneschi, Inboard’s CTO and co-founder), felt this way and actually did something about it. At university his bike was stolen three weeks in a row from a bike rack right outside of his classroom. To prevent this, he wanted something he could take inside with him. In addition to being portable, he wanted it to be fun, lightweight, and convenient. He started by taking drone motors and applying them to skateboards. About a year later, and after about five prototypes, he had something that was really cool. He and I would get mobbed wherever we went by people just wanting to buy them. This is when we knew we had a viable business here.

         

        How did you guys meet?

        Theo was a team rider for Europe and France, and I was a team rider for the US. We met through our love of action sports. He also has a background in mechatronics, electronics, and mechanical engineering.

         

        Inboard_skating 1.png

         

        How big is Inboard now?

        We’re 15 people, so still a startup. We have a huge focus on engineering, about half of our team is made up of engineers and the rest is sales, operations, and marketing. When we started our Kickstarter campaign it was the two of us and one other person, our designer, Paige. So we’re pretty thrilled with how scrappy we are.

         

        So how long did it take to go from Idea to the prototype M1?

        From idea to first working prototype was about 12 to 14 months.  Then we spent the last 14 months bringing it from prototype to production quality.

         

        Tell me a little about the design process? What lessons did you learn from the first few ideas that carried over into the final product?

        If you look at the product, one thing that gets people really excited is the design aesthetics; how minimalistic it is and how much it really looks like a skateboard. Coming from our backgrounds in action sports, we knew for something to be really adopted by the mass market it needs to get that core group of influencers excited. We knew the products that were out there just didn’t look cool. We looked to companies like Apple and Tesla, and even Dyson, that make things look cool. So we wanted to design something that felt like riding a regular skateboard, that gliding feeling, but also be able to have motors in the wheels and swappable batteries. Some of the elements we were familiar with as riders were missing from the current offerings.

         

        So, industrial design sounds like a big focus to make something that people would want to carry around with them. Were there any challenges you didn’t anticipate?

        The fact that we wanted to make an electric skateboard that at its thickest point was 24mm was a challenge. The only commercially available motor controller at that time was 44mm tall, so using off-the-shelf components wasn’t an option. The consequence of our decision to make design aesthetics a priority really dictated the rest of the course of development. We had to design our own custom electronics, the motor control, the battery pack, and everything else. I don’t think they were unforeseen, but it was a conscious decision to go for the top-tier design aesthetic and integration. A huge benefit for us is that we designed the entire drive frame, giving us the ability to control all the performance parameters of the product.

         

        Are there plans to expand beyond the M1?

        That’s the most exciting thing about what we’ve done. Because we focused on really clean design and we built our own electronics, we were able to perfect the performance. We now can look at the motor controller and battery as a platform. You can easily take this and put it into other form factors.

         

        Inboard Battery.png

          

        Was the success of the Kickstarter campaign a surprise?

        As with all crowdsourcing campaigns you hope for the best and plan for the worst. The Kickstarter platform has become the best way to launch a product. For Kickstarter, it’s about all the little details, the things to button up. Your brand isn’t just a logo, its how you interact with customers and this was a great trial for that.

         

        Tell me about some of the components, starting with the remote.

        We looked at all the remotes on the market and they all had lanyards that went around your wrist. We didn’t want lanyards, they felt dated. So we set out to design a remote that functions with the rider. It wraps around your finger so you can open and close your hand. Some companies are using a slider, where it moves back and forth. Other companies use a wheel, where after you push it forward the finger slips and you have to re-grip it every once in a while. We looked at the most common interfaces for someone controlling something and we landed on video game joysticks. The only difference is we restrict it to just forwards and backwards. Feedback has been great. It’s very precise and natural.

         

        Inboard Controller.png

         

        Explain the connectivity between the remote and the skateboard.

        We’re using Bluetooth with low-energy functionality. Having a robust, reliable connection is the most important thing. If you’re riding on flat ground and you need to stop, but can’t because your Bluetooth signal drops, you’ve got a dangerous situation. We didn’t want to skimp on any of our components. We realized that was the core of what would make us successful and it was worth the work that went into creating relationships with top tier suppliers to make it happen.

         

        How far can you go on one charge?

        Seven to 10 miles, which depending on how fast you’re going might be 25 minutes to more than an hour.

         

        Inboard Skating 2.png

         

        Is there a smart device involved in the connection between the skateboard and the remote?

        We have the Bluetooth on the remote, which is communicating with the motor controller on the board. And you can get data sent to your iPhone. So if you have an iPhone, you can see all the data, including battery level and range.

         

        When you set out on this project did you realize that connectivity would be such a critical factor?

        We always knew it would be important, but we didn’t realize how critically important it would be to bring so many other facets together. You look at it, and a skateboard that traditionally is kind of dumb can now have accelerometers and gyroscopes, and can map everything from the terrain to the quality of the street you’re on. If you ride through Austin and hit a pothole, the accelerometer can map that. Then I ride through 15 minutes later, I get a notification to watch out for it. It’s important for us to not only communicate with the product directly but also with the cloud to map routes and increase efficiency. Our vision is to reshape how we navigate urban environments.

          

        Can you use the M1 without any power, like a traditional skateboard?

        In designing our motor, we were able to design it to get rid of all cogging, which is when a magnet skips the sensor. It rolls like a normal skateboard. We also have regenerative braking, so when you’re braking going down a hill you’re also recharging the battery. Most EVs can do this with about 15 percent efficiency, and we’re doing round 30-40 percent.

         

        Inboard M1.png

         

        Can you tell me a little about how Silicon Labs came to be part of this project?

        We’re a startup and while we have a great team of engineers, it isn’t like coming from a big company where you have a massive support system. Inboard relies heavily on vendors for helping us develop our products. When we’re selecting people to work with it’s not so much about test and cost, but choosing a long-term, reliable partner. For us it’s making sure we have good support, good documentation, insight, and the ability to call support and get an issue fixed quickly. Having vendors that will really take their time with you and maybe hold your hand a little bit really gives you the confidence to take things to the next level.

         

        We use the BLE113 Bluetooth module, both in the remote and in the board. We had great support from you guys. We had one of your guys in Brazil spend about an hour with our electrical engineer going through everything at a deep level and helping us get the Bluetooth module on the motor controller to communicate with not only with the remote, but the iPhone.

         

        One of our competitors was having trouble because their Bluetooth connections were dropping in locations all over the world. They started a Google Map and dropped pins at all the locations where customers should be careful because they could lose control of the product. We’ve taken our board and a remote with a BLE113 module and we’ve gone to all of the places where they were losing connections in San Francisco. We’ve never lost a connection. Out of the box it’s better because we chose a better partner; for us that’s a huge win.

         

         

        Where do you see the future of IoT Heading?

        It’s interesting.  We changed pretty quickly from Inboard Action Sports to Inboard Technology because what we are doing here is applicable in everything from automotive to elderly care. We don’t fit the normal box of smart home application, but we have a product that maps streets, detects road conditions, and it’s happening without the user even realizing it. That’s the most exciting thing about the IoT space; two years ago everything was screaming ‘this is iot’ but now it’s in the background.

         

         

      • Sense is Everything: Enter to Win our Latest Thunderboard Inspiration Kit

        Lance Looper | 10/294/2016 | 10:55 AM

        What could you do with a Thunderboard Sense? We’re giving you the opportunity to find out by offering a chance to win one of our newest Thunderboard Inspiration Kit. The latest edition is small and feature-packed, bringing a load of high-quality sensors to this development platform for battery operated IoT applications. We’ve also built a free mobile app for quick proof-of-concept for cloud connected sensors so users can get up and running quickly.

         

        Sense-Nature1020.png

         

        The multi-protocol radio, combined with a broad selection of on-board sensors, provide an excellent platform to develop and prototype a wide range of battery powered IoT applications.

         

        Screen Shot 2016-10-20 at 9.49.03 AM.pngSo How do I Get Mine?

        Go here and fill out the registration form, it will take two minutes or less. Then, in November we’ll select 5 winners to receive a Thunderboard Sense. We can’t wait to see what you can do with it!

         

        Win Your Thunderboard Sense Here

         

        Need some inspiration? Check out what our friends over at Pump Studios did with the Thunderboard React!

      • High Quality Audio with I2S - Part 1

        lynchtron | 10/292/2016 | 03:09 PM

        13_title.png

        In this chapter, we will be making some noise!  Audio generation was something that I found difficult to understand and implement in my first embedded design.  For whatever reason, I could not find many examples to help me create loud and clear audio with an MCU.  Things can get complicated really fast with new terminology, and everything seems to be written for an expert, but I figured it out for the most part and I will share my findings.

         

        Many embedded devices utilize audio sound effects such as beeps or clicks for user feedback, and some devices can also deliver complex audio like speech and music.  These are two different goals for your embedded project, and they have different requirements.  In this chapter, we will learn how to generate high quality audio from sound files that you can create on your computer.  This is in some ways easier than creating more primitive sound effects on an MCU.  You will also learn how to read the audio data files from a Micro SD card that contain the sound files, with the help DMA.  The Ping Pong DMA mode is used and explained.

         

        The goal in this chapter is to just get our feet wet in learning about one way that audio can be generated by an MCU.  There are many ways to do it, and we will be exploring a few more ways to accomplish the same task in the next chapter, where we will also learn about amplification.  For now, we will be focusing on simply creating the audio with the help of an external Digital to Analog Converter (DAC) that we can communicate with using our USART peripheral in Inter-IC Sound (I2S) mode.

         

        Materials Needed for this Chapter:

         

        Cirrus Logic CS4344 Overview

        The Cirrus Logic CS4344 is a 24-bit, 192 kHz DAC that translates digital data received on its inputs via I2S into analog sound.  What do those numbers mean?  The number of bits is used to compute the maximum number of voltage steps used to reproduce the analog waveform.  Taken together, these are called bit rates.  With 24 bits, that creates about 17 million discrete voltage steps of resolution, which is incredibly accurate for even the most discerning audiophile.  The frequency of the DAC dictates how fast the DAC can output a new voltage value.  Since human hearing can only discern up to 20 kHz of audio, 192 kHz gives about 10 samples per period at 20 kHz, and 64 samples per period down in the 3 kHz range, where more of the audio information for human consumption is located.   Therefore, the CS4344 is a very capable device for high quality audio.

        13_bit_rates.png
        The I2S bus consists of a serial data signal called SDIN, a clock to latch the data called SCLK, and a word clock, which the CS4344 calls a LRCLK, for left-right clock.  This is the clock that selects whether the data on SDIN is for the left or right channel.  The CS4344 also requires a master clock called MCLK which is separate from the I2S bus requirement and drives the internal circuitry for the DAC. 

         cs434x_diagram.jpg

        The I2S data that is sent from the MCU to the CS4344 is uncompressed digital data that communicates a single 24-bit voltage per sample.  Since the CS4344 is a stereo DAC, the samples for the left and right channels alternate one after another in time, and it uses the LRCLK to designate a sample as a left or right channel.  Note that you are not required to use the maximum bit rates for this chip.  You can send in lower bit rates as long as the LRCLK to MCLK ratio is within the following ratios as required by the CS4344:

         

        13_clock_ratios.png


        Therefore, in order to use the CS4344, we must figure out a way to generate the MCLK so that the MCLK-to-LRCLK ratio falls somewhere in the valid region in the table.  This means that we either must already know the sample rate of the audio that we intend to play, be able to dynamically adjust MCLK for the audio file that we want to play, or be prepared to make conversions on the fly to a different rate.  By the way, the abbreviations SSM (single), DSM (double), and QSM (quad) are the speed modes and appear to be internal Cirrus Logic nomenclature that have no I2S implications.
         

        It is worth mentioning a note of warning on some of the content in this chapter.  This stuff is NOT easy to figure out!  It literally took me around ten hours of work to figure all of this out.  This is despite the fact that I already knew my way around audio formats, audio editing programs, and I have a computer engineering background.  It is always difficult to learn new chips.  The word engineer is shorthand for “really persistent person.”  Don’t ever give up.  The pain that you are feeling is completely normal.

         

        For my first attempt at using this chip, I found a small sound file that had a sample rate of 24000 Hz and was a 16-bit uncompressed WAV file with the .wav file extension.  There are a lot of files that can use this extension, and the format of the data is stored in the header for the file.  In order to find out information about my sound file, I opened up an open source program called Audacity, which allows me to see the waveform and the information about how the data is formatted.

         

        13_audacity.png 

        The filename is called sweet1.wav and the information about the waveform can be found to the left of the graph.  The file is a mono, or single channel, file at 24000 Hz sample rate.  Note that the 32-bit float label is actually incorrect.  This is actually a 16-bit 2’s complement data file, which is a way that computers can communicate both positive and negative numbers.  I don’t know why Audacity gets that wrong, but even if I export this as a 16-bit file, the file size is the same and I know from other tools that this is in fact a 16-bit file.  All of the other data indicated by Audacity is correct.

         

        I have placed my example audio files in the github repo here.  You can choose to use those or play your own, but we need to use uncompressed audio for the I2S bus, since the DAC provides no decompression.   Audacity can open many data formats of compressed audio files such as MP3 files and then export them as uncompressed Pulse Code Modulation (PCM) audio.  You can use this tool to play with sounds other than the ones in the repo.

         

        Once I had my test audio file, I had to figure out how to get everything working and started looking around for I2S examples.  I found one inside the EFM32 SDK under the DK3850 kit software called DK3850_wavplayer and imported it into Simplicity Studio as a new project.  It was written for either the internal DAC on the EFM32 or an external DAC via I2S.  So I lucked out and it allowed me to get started more easily than starting from scratch.  However, I soon found out that the CS4344 device that I had chosen requires an MCLK that needs to have a specific relationship to the LRCLK, which the DK3850_wavplayer didn’t implement. 

         

        In order to get this working, I began changing up the example wavplayer file, since once Simplicity Studio imported the project, it was my private copy to change all that I wanted.  The first order of business was to generate that MCLK that was at a ratio of 256 or 284 times the LRCLK frequency.  Table 1, above, starts at 32000 Hz, which is higher than my 24000 Hz file.  I figured that a ratio of 256 would probably work and I was proven correct.   The only problem is that 256 x 24000 Hz = 6.144 MHz for MCLK, and that is sort of an odd frequency for the MCU to generate.  My approach was to use a hardware timer but the fastest frequency that I could generate on a timer with the HFPERCLK (high frequency peripheral clock) running at 24 MHz results in a maximum timer frequency of 12 MHz.  That means that by dividing it down, I was stuck with very even stops of 8 MHz, 6 MHz, 4.8 MHz, and so on, with nothing else in between.  There was no ability to generate an exact 6.144 MHz clock with the onboard peripherals.  Had I realized this when I selected this CS4344 part, I probably would have looked for a different part or find some other off-board component that could generate that particular frequency.  By picking the closest frequency of 6MHz for MCLK, which is about 98% of the ideal frequency, our sounds will play 2% slower than intended.

         

        Here was the code that was added to the DK3850_wavplayer example to give a 6 MHz clock on a GPIO pin:

        // Toggle GPIO pin PD7 for MCLK
        void create_gpio_clock()
        {
              CMU_ClockEnable(cmuClock_TIMER1, true);
              CMU_ClockEnable(cmuClock_GPIO, true);
         
              // Enable MCLK output
              GPIO_PinModeSet(MCLK_PORT, MCLK_PIN, gpioModePushPull, 0);
         
              // Create the object initializer for compare channel
              TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
              timerCCInit.mode = timerCCModeCompare;
              timerCCInit.cufoa = timerOutputActionNone;
              timerCCInit.cofoa = timerOutputActionToggle;
              timerCCInit.cmoa = timerOutputActionNone;
              timerCCInit.filter = true;
         
              // Configure TIMER1 CC channel 1
              TIMER_InitCC(TIMER1, 1, &timerCCInit);
         
              // Route CC1 to location 1 (PD7) and enable pin for cc1
              TIMER1->ROUTE |= (TIMER_ROUTE_CC1PEN | TIMER_ROUTE_LOCATION_LOC4);
         
              // Set TIMER Top value to 3, to generate 6MHz clock
              TIMER_TopSet(TIMER1, 3);
         
              /* Select timer parameters */
              TIMER_Init_TypeDef timerInit =
              {
              .enable     = true,
              .debugRun   = true,
              .prescale   = timerPrescale1,
              .clkSel     = timerClkSelHFPerClk,
              .fallAction = timerInputActionNone,
              .riseAction = timerInputActionNone,
              .mode       = timerModeUp,
              .dmaClrAct  = false,
              .quadModeX4 = false,
              .oneShot    = false,
              .sync       = false,
              };
         
              /* Configure timer */
              TIMER_Init(TIMER1, &timerInit);
        }

         

        I commented out any code in wavplayer.c that had to do with BSP (board support package), buttons, and volume control.  My goal was just to produce sound after reset at this stage.  Now that the MCLK is running, we can finally try out reading from the MicroSD card and getting some audio going. 

         

        We will connect to the MicroSD card and read some files in the next section.

         

         PREVIOUS | NEXT

      • Defeating the Challenges of Electromechanical and Solid-State Relays

        Lance Looper | 10/292/2016 | 11:10 AM

        Electromagnetic relays (EMRs) are broadly used in motor control, automotive, HVAC, valve control, solar inverter and many other industrial applications. Over the last 10 years, solid-state relays (SSRs) have seen fast growth as they begin to replace EMRs. Designers have found that SSRs can address most of the limitations of EMRs. But as is often the case with alternative solutions, SSRs have their own set of tradeoffs that can challenge designers. A third alternative exists: using custom SSRs. Let’s exam the limitations and tradeoffs of each approach.

         

        Fast Growth of SSRs at the Expense of EMRs

        Electromechanical relays use a coil that when sufficiently powered can move an armature to switch contacts based on the magnetic flux generated. EMRs have the benefit of truly being off without leakage current when not energized. However, they have many limitations that SSRs can address, which is contributing to SSR market growth. SSRs have no moving parts as they are based on semiconductor technology, which directly contributes to better reliability, much longer lifetime and fast switching speed. As EMRs switch, the contacts generate both acoustical and electrical noise along with arcing, which makes them unsuitable in some applications. EMRs are bulky, often impacting industrial design and placement options on a printed circuit board (PCB).

         

        The typically large, through-hole EMRs also increase manufacturing cost versus smaller surface-mount SSRs.

         

        Design Challenges of Optocoupler based SSRs

        As designers look to SSRs to address EMR limitations, they are finding a different set of challenges. SSRs offer small board space when used in low-power switching applications. However, higher power switching applications must use larger custom packages to deal with the power dissipation and heat of the integrated FETs. Quite often the SSR user must compromise on FET performance, power or cost as there are limited choices of integrated FETs.

         

        SSRs typically use optocoupler based designs to achieve isolation. These optocoupler designs have inherent LED limitations such as poor reliability and stability across temperature and time. A key optocoupler wear-out mechanism is LED light output. As LEDs age their light output declines, which negatively impacts timing. The degradation in light output grows worse over time with increased temperature and higher currents.

         

        Other common issues include unstable input current thresholds and complicated current transfer ratio. Designers are forced to use more current and add external components to address these issues or use alternatives to optocoupler-based isolation. More and more industrial applications such as industrial drives, solar inverters, factory automation and metering are targeting 20+ years of system life so it is important for the designer to carefully consider these effects on the system lifetime.

         

        Alternative Custom SSR Using Optocoupler-Based Isolation

        Many system designers prefer to use existing high volume and cost-effective discrete FETs as their performance and thermal characteristics are well understood in contrast to the often unknown integrated FETs of SSRs in non-standard packaging. A custom SSR enables the use of these application optimized FETs instead of the typically compromised FETs that are integrated into SSRs. There is a tradeoff in board space versus low-power switching SSRs, but this tradeoff becomes less important with higher powered SSRs due to heat dissipation challenges of integrated SSRs.

         

        The figure below shows a custom SSR based on traditional optocoupler based isolation. A secondary, switch side power supply is usually required with these types of solutions as power is not transferred across the isolation barrier.

         

        Custom SSR.png

         

        Alternative Custom SSR Using CMOS-Based Isolation

        Over the last few years, multiple semiconductor suppliers have introduced more advanced CMOS-based isolation products with double-digit growth over traditional optocoupler based isolation. This is especially true in high temperature and high reliability industrial applications. Traditional optocoupler based custom SSRs can address the limitations of integrated FETs but require an additional power supply. Even then, customer SSRs built around an optocoupler cannot address the inherent limitations of using LEDs. Another alternative is now available that enables developers to use their choice of application specific, high volume FETs without the disadvantages of optocoupler based designs as shown below.

         

         

        Custom DC Switching.png

         

        The Silicon Labs Si875x family features the industry’s first isolated FET drivers designed to transfer power across an integrated CMOS isolation barrier, eliminating the need for isolated secondary switch-side power supplies and reducing system cost and complexity. Since Si875x drivers do not use LEDs or optical components, they provide superior stability over time and temperature with up to 125˚C automotive operation. A single Si875x can support either dc or ac load switching with one FET required for dc load switching as shown in Figure 2 or two FETs for ac load switching as shown here.

        Custom AC.png

         

         

        Developers have the option to use a CMOS digital input with the Si8751 (Figure 2) or the diode emulation input of the Si8752 (Figure 3). The Si8752 isolated FET driver makes it easy for developers to migrate from optocoupler-based solutions while efficiently generating a nominal 10.3 V gate drive using only 1 mA of input current. Optional miller clamp inputs are implemented that allow the addition of a capacitor to eliminate the possibility of inductive kickback changing the state of the switch when used in applications with high dV/dt present on the FET’s drain. The Si8751 easily interfaces with low-power controllers down to 2.25 V and provides a unique low-power TT mode that provides exceptionally fast turn-on speeds, as fast as 100 µs, while dropping static holding current as much as 90 percent. An optional capacitor is tied to ground using the TT pin to enable this power-saving feature. This approach allows the device to draw more current to initially switch the external FET on quickly yet draw less supply current in the steady state. Total power over time is reduced while maintaining the FET’s fast switching speed.

         

        Developers face continual challenges to implement next-generation designs with lower system cost, higher performance and better reliability. Offering a unique combination of robust, reliable CMOS-based isolation technology and advanced capability to transfer power across the isolation barrier, new isolated FET drivers now provide a much-needed replacement solution for antiquated EMRs and optocoupler-based SSRs. CMOS-based isolated FET drivers give developers the flexibility to choose a cost-effective FET customized to their application needs, creating an easy migration to state-of-the-art solid-state switching.

         

        For more information on the Si875x isolated FET driver family, click here.

         

        This article originally appeared in PowerPulse.net

      • October 2016 Member Spotlight: Yuriy

        Nari | 10/288/2016 | 10:34 AM

        We are featuring one of the Silicon Labs Community members who is active or new in the community on a monthly basis to help members connect with each other.

         

        Meet our October member of the month: Yuriy

        profile (1).png

         

        Q: Congrats on becoming our featured member of the month! Can you introduce yourself to our community members?

         

        First of all thank you very much for choosing me as the member of the month!


        My name is Yuriy Gerasimov, and I'm from the south of Russia (Krasnodar). I have about 15 years of experience in embedded system/software and work as part-time/contract engineer for several companies now days, based at Germany, Netherlands, Austria and Russia. Worked in big companies (like Samsung Electronics) and small startups guided from crowdfunding to mass production successfully. So I have got quite interesting, wide and valuable experience in HW and SW.

         

        Last year with my partners, we also developed and sold EFM32-based automotive modules, EFM8/ EFM32 MCU-controlled LED drivers, BGM111 Bluetooth diesel engine booster and some more. As a hobby project and for self-development, I started this LCD Sensor Logger device project, hope to complete it somehow despite of this cold autumn weather, my two lovely little kids and wife, plus permanent lack of time Robot Happy

         

        light values.png

        Portable sensor logger with LCD, Bluetooth LE & cloud connection

         

        Q: How did you know about the Silicon Labs Community?

         

        Well, several years ago, I had to make a decision and chose 32-bits ARM Cortex-M MCU manufacture to go further and move away from 8/16 bits core MCUs. There were several requirements like: price, free and cross-platform IDE, MCU interfaces & functionality, low-power, documentations/app.notes/ examples, customer friendly/community support, availability in different countries, including Russia (sometimes it's pretty tough Robot Happy ) . And EFM32 won, that's a way I got into Silicon Labs Community. After EZR32/BGM/WGM modules introduction I moved all of my new projects on Silicon Labs solutions, except of customer's special wishes.

         

        Q: What features would you like to see added to the community?

         

        Well, everything is very good, there are forums, training, blogs and tools. Would be nice for me to see more Knowledge Base and Training articles about IoT and wireless. But I see it's in progress now.

         

        Q: What advice would you give to someone new to the community?

         

        Just read docs, app notes and search deeper, probably your problem already solved by someone. And to make the new topic header correctly.

         

        Q: Thanks for answering the questions. Any final comment?

         

        Thank you Silicon Labs for such a cool products, customer-friendly support and community!

         

      • Drive a TFT LCD with Capacitive Touchscreen - Part 4

        lynchtron | 10/286/2016 | 04:23 PM

        12_title.png

        In this last part of a four-part series, we will connect to the touchscreen's capacitive touch sensor over I2C and use that information to place a small rectangle on the screen.  Then, we will build a touch-enabled color palette and use that control widget to change the color of the dot, thereby completing a simple finger painting application.

         

        The capacitive sensor on this display board is the FT6206 from Focal Tech Systems.  Its specification, FT6x06+Datasheet_V0.1_Preliminary_20120723.pdf, shares some technical details about the chip, the electrical ratings, packaging, and pinout information, which will all be necessary if you intend to include this part in a design from scratch.  However, the spec is pretty sparse for the kind of information that we need for software.  To find more details about the software interface, you need to look in the application note FT6x06_AN_public_ver0.1.3.pdf. 


        We have communicated with the I2C bus in chapter 10, so we can reuse some of our code for this chapter.  However, the accelerometer from chapter 10 and the capacitive sensor have some differences in how they make use of the I2C bus.  The capacitive sensor’s spec details the I2C cycle requirements in the following figure.

         12_focal_tech_spec.png


        The FT6206 capacitance sensor requires us to first write the offset into the I2C register space (i.e. the “data address” in the figure) with a Set Data Address command.  All write and read cycles that follow this command will begin at that offset.  Then, in the case of a write, the next I2C packet is a repeated write packet, with no need to resend the device address.  The write packets continue until the slave device sees a stop bit.  In the case of a read, the Set Data Address command is terminated once the Data Address is set, and the next I2C cycle is a simple read command that begins with the device address in the first packet and then continues with repeated read packets as long as the I2C master keeps sending the I2C ACK condition.

         12_i2c_cycles.png

        In chapter 10, we made use of the I2C_WRITE_WRITE_FLAG and the I2C_WRITE_READ_FLAG with the accelerometer device in order to resend the I2C device address after the first offset address packet as the accelerometer required.  This required two different buffers be loaded into the I2C transfer function, one for the offset address, and one for the data that was to be transferred to that offset.  With the FT6206 capacitance sensor, we will only need to make use of the I2C_WRITE_FLAG and the I2C_READ_FLAG.  Therefore, only one buffer will be required for the I2C transfer function.

         

        // Used by the read_register and write_register functions
        // data_array is read or write data, depending on the flag
        void i2c_transfer(uint16_t device_addr, uint8_t data_array[], uint16_t data_len, uint8_t flag)
        {
              // Transfer structure
              I2C_TransferSeq_TypeDef i2cTransfer;
         
              // Initialize I2C transfer
              I2C_TransferReturn_TypeDef result;
              i2cTransfer.addr          = device_addr;
              i2cTransfer.flags         = flag;
              i2cTransfer.buf[0].data   = data_array;
              i2cTransfer.buf[0].len    = data_len;
         
              // Set up the transfer
              result = I2C_TransferInit(I2C0, &i2cTransfer);
         
              // Do it until the transfer is done
              while (result != i2cTransferDone)
              {
                    if (result != i2cTransferInProgress)
                    {
                          DEBUG_BREAK;
                    }
                    result = I2C_Transfer(I2C0);
              }
        }

        With this function, we can do a simple fetch of many registers in the device with a single read command.  Note that we require the I2C bus device address for the FT6206 capacitance sensor, and unfortunately, that data is not found in the datasheet or application note.  I found the address (0x38) in the Adafruit C++/Arduino drivers.   Don’t forget that the emlib I2C library requires that the device address be shifted once to the left as shown here.

         

        #define FT6206_ADDR           0x38 << 1
        #define FT6206_FIRMID_OFFSET  0xA6
        uint8_t data_array[16];
        // Tailored for the FT6x06 device only
        void i2c_read_device_id()
        {
              // First, set the address to read
              data_array[0] = FT6206_FIRMID_OFFSET;
              i2c_transfer(FT6206_ADDR, data_array, 1, I2C_FLAG_WRITE);
         
              // Then, do the actual read of the register contents, from the offset +9
              i2c_transfer(FT6206_ADDR, data_array, 9, I2C_FLAG_READ);
         
              // Check FT6206_FIRMID_OFFSET + 2 for FocalTech’s Panel ID = 0x11
              if (data_array[2] != 0x11)
              {
                    DEBUG_BREAK
              }
              return;
        }
        i2c_read_device_id();
        We can then build a function to read the registers that contain the touch characteristics, which are located up to offset 0xE, first into a data_array, and then into a data structure.
        uint8_t data_array[16];
         
        // Data structures to hole current capacitance sensor data
        typedef struct cap_data_type
        {
              bool touched;
              uint8_t touch_id;
              uint16_t x_position;
              uint16_t y_position;
        } cap_data_struct;
         
        cap_data_struct touch_data[2];
        uint8_t num_touch_points = 0;
        bool interrupt_triggered = false;
        uint16_t pen_color;
        // Helper function to convert touchscreen coordinates to touch screen coordinates
        uint16_t map(uint16_t x, uint16_t in_min, uint16_t in_max, uint16_t out_min, uint16_t out_max)
        {
          return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
        }
         
        void i2c_read_capacitance_values()
        {
              // First, set the address to read
              data_array[0] = 0;
              i2c_transfer(FT6206_ADDR, data_array, 1, I2C_FLAG_WRITE);
         
              // Then, do the actual read of the register contents, from the offset +15
              i2c_transfer(FT6206_ADDR, data_array, 15, I2C_FLAG_READ);
         
              num_touch_points = data_array[0x2] & 0x0F;
              for (int i=0; i < num_touch_points; i++)
              {
                    uint8_t base_offset = 0x3 + i * 0x6;
         
                    // Check the status, and shift over by 6 to compare bits 7:6 to 0b11
                    uint8_t status = data_array[base_offset];
                    if (((status >> 6) & 0b11) == 0b11)
                    {
                          touch_data[i].touched = false;
                    }
                    else
                    {
                          touch_data[i].touched = true;
                    }
         
                    touch_data[i].touch_id = data_array[base_offset + 0x2] & 0xF0;
                    uint16_t raw_x = data_array[base_offset + 0x1] + ((data_array[base_offset] & 0x0F) << 8);
                    uint16_t raw_y = data_array[base_offset + 0x3] + ((data_array[base_offset + 0x2] & 0x0F) << 8);
                    touch_data[i].x_position = map(raw_x, 0, ILI9341_TFTWIDTH, ILI9341_TFTWIDTH, 0);
                    touch_data[i].y_position = map(raw_y, 0, ILI9341_TFTHEIGHT, ILI9341_TFTHEIGHT, 0);
              }
        }


        The i2c_read_capacitance_values() function reads the FT6206 register space into the data_array variable, then maps the coordinates of the capacitive sensor to match the coordinates of the LCD screen.  Once again, this information was not found in the spec, and I needed to hunt through the Arduino drivers to determine the mapping.  The function then fills the touch_data array struct with the decoded register map of the FT6206 as found in the specification.

         12_touch_registers.jpg

         

        Now that we have a function that can fetch the capacitance values whenever we need them, the next step is to build a GPIO interrupt handler that can respond to a valid touch and let us know when we need to fetch touch coordinates.

        // Callback for capacitive sense IRQ
        int gpio_int_handler_process_touch(uint8_t pin)
        {
              // Read the capacitance values into touch_data[]
              i2c_read_capacitance_values();
         
              interrupt_triggered = true;
         
              return 0;
        }

         

        This function will be set up in main() in the code that follows.  When a valid touch is found, we can pass the x/y coordinates of the capacitance sensor through to the ILI9341 to draw a small square on the display using the draw_filled_rectangle() function wherever the capacitance sensor’s registers indicate a valid touch. 

        We need some helper functions to be defined to set the drawing pen color and draw the color palette across the top of the screen.

         

         

        #define BOXSIZE 40
        void select_pen_color(uint16_t color)
        {
              uint16_t box_x_start;
              // First, unhighlight the old pen color
              switch (pen_color)
              {
                    case ILI9341_RED: { box_x_start = 0;  break;}
                    case ILI9341_YELLOW: { box_x_start = BOXSIZE;  break;}
                    case ILI9341_GREEN: { box_x_start = BOXSIZE*2;  break;}
                    case ILI9341_CYAN: { box_x_start = BOXSIZE*3;  break;}
                    case ILI9341_BLUE: { box_x_start = BOXSIZE*4;  break;}
                    case ILI9341_MAGENTA: { box_x_start = BOXSIZE*5;  break;}
              }
              draw_unfilled_rectangle(box_x_start, 0, BOXSIZE, BOXSIZE, 6, pen_color);
         
              // Now highlight the new color
              pen_color = color;
              switch (pen_color)
              {
                    case ILI9341_RED: { box_x_start = 0; break;}
                    case ILI9341_YELLOW: { box_x_start = BOXSIZE;  break;}
                    case ILI9341_GREEN: { box_x_start = BOXSIZE*2;  break;}
                    case ILI9341_CYAN: { box_x_start = BOXSIZE*3;  break;}
                    case ILI9341_BLUE: { box_x_start = BOXSIZE*4;  break;}
                    case ILI9341_MAGENTA: { box_x_start = BOXSIZE*5;  break;}
              }
              draw_unfilled_rectangle(box_x_start, 0, BOXSIZE, BOXSIZE, 6, ILI9341_WHITE);
        }
         
         
        void draw_color_palette()
        {
              draw_filled_rectangle(0, 0, BOXSIZE, BOXSIZE, ILI9341_RED);
              draw_filled_rectangle(BOXSIZE, 0, BOXSIZE*2, BOXSIZE, ILI9341_YELLOW);
              draw_filled_rectangle(BOXSIZE*2, 0, BOXSIZE*3, BOXSIZE, ILI9341_GREEN);
              draw_filled_rectangle(BOXSIZE*3, 0, BOXSIZE*4, BOXSIZE, ILI9341_CYAN);
              draw_filled_rectangle(BOXSIZE*4, 0, BOXSIZE*5, BOXSIZE, ILI9341_BLUE);
              draw_filled_rectangle(BOXSIZE*5, 0, BOXSIZE*6, BOXSIZE, ILI9341_MAGENTA);
        }

         

        Finally, in the main() function, after the LCD has been initialized, we can build the finger painting app.

         

         

              draw_filled_rectangle(0,0, ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT, ILI9341_BLACK);
              tft_print(60,100, ILI9341_RED, "FINGER PAINTING");
              tft_print(40,160, ILI9341_WHITE, "Touch screen to start");
         
              // Check to see that we can talk to the i2c capacitive sensor
              i2c_read_device_id();
         
              // Set up capsense interrupt
              set_gpio_interrupt(gpioPortD, 13, false, true, (GPIOINT_IrqCallbackPtr_t) gpio_int_handler_process_touch);
         
              draw_color_palette();
         
              bool activated = false;
              /* Infinite loop */
              while (1)
              {
                    // Keep checking after the first interrupt until the event is over
                    if (interrupt_triggered)
                    {
                          i2c_read_capacitance_values();
                          if (!activated)
                          {
                                // Clear the screen and display the color palette
                                draw_filled_rectangle(0,0, ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT, ILI9341_BLACK);
                                draw_color_palette();
                                pen_color = ILI9341_RED;
                                select_pen_color(pen_color);
                                activated = true;
                                delay(100);
                                continue;
                          }
                    }
         
                    // Process any touches
                    for (int i=0; i<num_touch_points; i++)
                    {
                          if (touch_data[i].touched)
                          {
                                uint16_t x = touch_data[i].x_position;
                                uint16_t y = touch_data[i].y_position;
         
                                if (y < BOXSIZE)
                                {
                                      if (x < BOXSIZE) select_pen_color(ILI9341_RED);
                                      else if (x < BOXSIZE*2) select_pen_color(ILI9341_YELLOW);
                                      else if (x < BOXSIZE*3) select_pen_color(ILI9341_GREEN);
                                      else if (x < BOXSIZE*4) select_pen_color(ILI9341_CYAN);
                                      else if (x < BOXSIZE*5) select_pen_color(ILI9341_BLUE);
                                      else select_pen_color(ILI9341_MAGENTA);
                                      delay(200);
                                      continue;
                                }
                                draw_filled_rectangle(x, y, x+6, y+6, pen_color);
                          }
                          else
                          {
                                interrupt_triggered = false;
                          }
                    }
                    num_touch_points = 0;
         
              }

         

        Note that the display is slow, thanks to our single-data-bit SPI bus.  So you have to move your finger slowly to build the example image.  It would work much quicker if you were to hook up all eight of the data interface lines.

         

        Displaying a picture from a microSD on the LCD board

        Since we have access to a MicroSD card slot on the display, we can load more interesting graphics to the screen in the form of actual image data.  The MicroSD memory chip is accessed on the same SPI bus as the display, and so we will need to control the chip select (CS) signal directly.

         

        Since we have already worked with MicroSD cards in chapter 9, you should be able to accomplish this task on your own.  See if you can do it! 

         

        Here are some notes to help you out:

        1. Disable the AUTOCS as well as the USART_ROUTE_CSPEN in the peripheral_setup() function. This will allow you to control the chip select (CS) signal, PD3, through software.
        2. Manually assert (to low) the CS signal before calling on the SPI USART_Tx() function and deassert the CS signal (to high) after the USART_Tx() function.
        3. Get the LCD screen working with the new CS changes before you attempt to read from the MicroSD card.
        4. Decide if you want to use a computer to format the MicroSD card as a FAT file system and put image data on to it from a computer, or if you will store data directly on the card with no file system. This will require that you first connect to a USB-to-UART and load the image data over the serial port to get the image data onto the MicroSD card.
        5. Make sure that the image is saved at 16-bit color BMP format, and exactly the size that you intend to place on the screen, which is 240x320. You can use the Gimp image editing program to help you format your images.
        6. There is a structure to the BMP format, so you need to get past the header information before you get to the 16-bit color data for the image.
        7. Fill up a buffer of data from the MicroSD card, such as 512 bytes, then empty the buffer to the LCD after performing a Memory Write command to the LCD.
        8. Don’t forget to assert the MicroSD card CS signal, PD8, before any calls to read data, and then deassert it as soon as the transfer is complete.

         

        This completes the chapter on the LCD capacitive touchscreen.  With the EFM32 and emlib, we were able to build a simple finger painting application with about 500 lines of code (and a few supporting files).

        Remember, use a better interface (with lots of parallel connections) and a real graphics library when you embed a display in your gadget.  Also, make sure that you have the bandwidth and pins required for the performance that you expect.

         

         PREVIOUS | NEXT

      • RTOS Development Made Easy

        Alf | 10/286/2016 | 09:26 AM

        Update: This article has been edited to better reflect the needed toolchains.

         

        Ever wondered how to get started on your first RTOS project? Want to get a visual feel for how an RTOS operates and schedules events? This blog is a super-quick walkthrough on how to get started with μC/OS-III from Micrium on the Silicon Labs EFM32 Giant Gecko, using SystemView from SEGGER.

         

         

        Prerequisites:

        1. You need the latest version of Simplicity Studio to run this demo. You can download that here: www.silabs.com/simplicity
        2. You need to update the kit firmware to the latest version to support Real-Time Trace (RTT). The "Update firmware"-button should be easily recognizable from the "Launcher" in Simplicity Studio.
        3. You need the latest version of J-link software to support RTT. You can download that here: https://www.segger.com/downloads/jlink
        4. You need IAR for compiling. This demo has only been ported to the IAR compiler, so you will need that. You can download a free trial here: https://www.iar.com/iar-embedded-workbench/#!?device=EFM32GG990F1024&architecture=ARM

         

        Steps:

        1. The SystemView application that runs on the host computer is available for Windows, Mac and Linux computers. Download and install the SystemView Installer for the host PC from one of the following links:
        1. The zip file from this link https://www.dropbox.com/s/xvd9if3dqrjd64z/SystemView-uCOS-EFM32-GiantGecko.zip?dl=0 contains a Simplicity Studio project for the EFM32 Giant Gecko Starter Kit. Extract the zip file to a folder in your computer.
        1. Open Simplicity Studio, click the button Simplicity IDE and switch to the Development perspective, click File -> Import…, select the option Existing Projects into Workspace under the General category and click Next to import the project.
        1. Configure the root directory by browsing to the folder in your computer where you extracted the zip file in Step 2, select Copy projects into workspace and click Finish.
        1. Click Project and then Clean… to rebuild the project.
        1. Connect the Giant Gecko Starter Kit to your computer from the J-Link USB port.
        1. Expand the node Binaries in the Project Explorer and select the ELF file (extension .out)
        1. Create a new Debug Configuration, by dropping down the Debug button on the top toolbar and selecting Debug Configurations…
        1. Select Silicon Labs ARM Program and click the New Launch Configuration button on the top toolbar of the dialog window.
        1. Click the Debug button
        1. Click F8 to resume execution
        1. Halt the CPU by clicking the Pause button on the top toolbar of the IDE and then click the button right next to it to disconnect the debugger from the target.
        1. Open SystemView and click Target from the menu options at the top.
        1. Click Start Recording
        1. Enter the device name EFM32GG990F1024 as shown below and click OK to start the streaming of events. 

        segger_systemview.png

         

         

        And voilá: SystemView is streaming the RTOS-events directly to your computer:

         

        segger_systemview2.png

         

        When you want to understand more about system view, click here. 

      • Reduce Cost and Board Footprint in Your Next 8-bit Embedded Design

        Lance Looper | 10/284/2016 | 12:34 PM

        This article originally appeared as a How-To article in EDN Magazine. 

         

        General 8-bit MCU

        Reducing bill of materials (BOM) cost and footprint area are among the top design considerations for microcontroller (MCU)-based embedded designs. One way to achieve these design goals in 8-bit MCU designs with switching converters is to drive these switching converters with a high-frequency clock output rather than with a traditional pulse-width modulation (PWM) output at lower frequencies. This technique enables a reduction in the switching converter inductor size, resulting in reduced BOM cost and board space requirements.

         

        Background

        Switching converters are commonly used to efficiently step-up or step-down voltages within embedded systems. These converters use an inductor to store and then transfer energy to the load in the system. The inductor is periodically switched on to transfer energy from the supply into the magnetic field of the inductor. When the supply is switched off, the inductor transfers its energy into the load. These converters are generally switched on and off by a PWM signal, and the signal characteristics can influence the output characteristics of the converter.

         

        Let’s consider, for example, a boost converter, which is a switching converter that generates an output voltage that is greater than the input voltage.

         

        Continuous mode

        Generally, boost converters are operated in "continuous" mode. This means that the inductor in the converter is not fully discharged (i.e., current in the inductor does not reach zero) between switching cycles.

        The formula for determining the output voltage of a continuous mode boost converter is rather simple:

         

        Continuous Mode Formula.png

         

        Where Vo equals the output voltage, Vi equals the input voltage, and D equals the duty cycle percentage. In this case, the output voltage can be varied by simply changing the duty cycle of the PWM of the switching element. However, this mode comes with one caveat: the inductor must be large enough to store the energy required by the system during its charge and discharge cycles. This means the slower the switching frequency, the longer the inductor has to charge and discharge, and thus the larger the inductor must be. Larger inductors are, of course, more expensive, so generally switching converter designs favor higher switching frequencies over lower switching frequencies.

         

        There is an upper limit to the benefits of a higher switching frequency, however. As switching frequencies increase, losses also increase within the switching element of the circuit (usually a MOSFET), and inside the inductor, so there is an upper limit on switching frequency once these losses become prohibitively large.

         

        Some 8-bit MCUs, such as Silicon Labs’ C8051 and EFM8 devices, have the ability to generate PWM outputs with varying duty cycles using the programmable counter array (PCA) module, which means they are well-equipped to drive boost converters in continuous mode. However, the maximum PWM frequency is often as low as 95.7 kHz (the fastest internal oscillator is usually 24.5 MHz, which is then divided by 256 for 8-bit PWM), which is rather slow by switching converter standards. This means that, generally, 8-bit MCUs operating switching converters in continuous mode will require relatively large, and thus expensive, inductors.

         

        Online calculators are available to help developers determine the required components in a continuous mode boost converter, such as DIY DC/DC boost calculator. For example, let’s use the following design requirements:  

        Vin = 3 V

        Vout = 12 V

        Iout = 20 mA

        Switching Frequency = 95.7 kHz

         

        We will need to run our switching converter at 75 percent duty cycle with a 147 µH inductor.

         

        Discontinuous mode

        An alternative to continuous mode is "discontinuous" mode in which the inductor current is allowed to reach zero during the discharge period of the switching cycle. This approach has the side effect of complicating the formula for the output voltage:

        Output voltage.png

         

        Where L is the inductor value, Io is the output current, and T is the switching period (the inverse of the switching frequency). As you can see, the formula is more complicated, and it still contains the duty cycle percentage as a dependency, but it has introduced additional dependencies that we can use to generate the desired output, even with a fixed duty cycle. For example, with everything else fixed, if we decrease both T and the inductor size L proportionally, the output characteristics will remain the same. This means that we can use an arbitrary duty cycle, and then increase the switching frequency as needed to reduce the inductor size and cost.

         

        The PCA, once again, has a feature that can be useful in this mode: frequency output generation. In this mode, a 50 percent duty cycle frequency output can be generated, up to SYSCLK divided by 2, or 12.25 MHz in the normal case. Due to the previously mentioned switching losses, switching converters are not usually operated at frequencies as high as this, typically operating in the range of 100 kHz to 4 MHz. At a more reasonable switching frequency of 3.062 MHz (a 24.5 MHz SYSCLK divided by eight), we can repeat our previous example, this time using discontinuous mode with a fixed 50 percent duty cycle:

         

        Vin = 3 V

        Vout = 12 V

        Iout = 20 mA

        Switching Frequency = 3.062 MHz

        Duty Cycle = 50%

         

        With this, the required inductor size is reduced to 2.04µH! That's approximately 1/72nd the size of the continuous mode with PWM example, for the same output characteristics.

         

        Comparing inductors at ~2.2 µH vs ~150 µH, that are otherwise comparable:

         

        SRN4026-151M : 150 µH, 220 mA: $0.18 @1000 : 4×4mm

        MLZ2012A2R2M : 2.2 µH, 210 mA: $0.058 @1000 : 2×1.25mm

         

        As you can see, this smaller inductor results in a BOM cost reduction of 12.2 cents, or a 68 percent reduction. The footprint is also reduced by 11.5mm2, or 72 percent.

         

         

        Example circuit and firmware

        As a proof of concept, we have developed a circuit and associated firmware. In the previous example, the characteristics of the circuit are static. As long as Vin is 3V, and the load continues to draw 20 mA at 12V, the MCU merely needs to output a 3.062 MHz square wave to the switching circuit to maintain a stable output. If the load draws less than 20 mA at 12V, the output voltage will continue to increase until equilibrium is reached. Without any sort of feedback mechanism, we cannot be sure of the output voltage if the load varies.

         

        In the following circuit, a voltage divider has been provided to allow the MCU to measure the output voltage, and thus create a feedback loop, enabling us to change the behavior of the output at runtime. Regulating the output voltage can be accomplished by disabling the frequency output when the output voltage is too high, and re-enabling it when the output voltage is too low. Additionally, a dummy load, represented by R4 and the LED, has been attached to the output.

         

        Output.jpg

        Example Circuit Design

         

        The firmware was written for an EFM8BB1 MCU, though this could be ported to any 8-bit MCU with a PCA module and an analog to digital controller (ADC) with the Window Compare feature. The PCA is configured to output Channel 0 to pin P0.1, with a frequency output of 3.062 MHz. The ADC is configured to sample on pin P0.3 at 300 kHz, using Timer 3 overflows to trigger conversions. The ADC is configured to only trigger an interrupt if an ADC sample falls outside of the expected voltage range, using the Window Compare feature. With everything configured, the entire feedback loop is contained within the ADC ISR:

         

        SI_INTERRUPT (ADC0WC_ISR, ADC0WC_IRQn)

        {

                        uint16_t sample;

         

                        // Clear Window Compare interrupt flag

                        ADC0CN0_ADWINT = 0;

         

                        // Store the ADC sample

                        sample = ADC0;

         

                        if (sample > MAX_COUNTS)

                        {

                                        // Disable PWM

                                        P0MDOUT &= ~P0MDOUT_B1__BMASK;

         

                                        // Set LT Value, Clear GT Value

                                        ADC0LT = MIN_COUNTS;

                                        ADC0GT = 0xFFFF;

                        }

                        else if (sample < MIN_COUNTS)

                        {

                                        // Enable PWM

                                        P0MDOUT |= P0MDOUT_B1__PUSH_PULL;

         

                                        // Set GT Value, Clear LT Value

                                        ADC0LT = 0;

                                        ADC0GT = MAX_COUNTS;

                        }

        }

         

        If the ADC takes a measurement that is greater than the ADC0GT value or less than the ADC0LT value, this interrupt will fire. If the measurement is within this range, nothing will happen. Once in the ISR, if the measurement was greater than the expected maximum value, the frequency output is disabled. If it is less than the expected value, the frequency output is re-enabled. The output is effectively disabled by turning the port to open-drain mode, so that the pin is pulled low by the resistor R1, turning off the MOSFET Q1.

         

        The MAX_COUNTS is defined to be the ADC code that represents 9.5V. MIN_COUNTS represents 8.5V. This should effectively limit the output voltage to 8.5-9.5V.

         

        The following oscilloscope image shows the output of the circuit with this code.

         

        oscilloscope.jpg

         

        Channel 1 is the output voltage. Channel 2 is the frequency output that is applied to the circuit's BOOST pin. As you can see, this firmware activates the frequency output when the voltage is below 8.5V and disables the frequency output when the voltage is above 9.5V.

         

        In practice, the usage of the ADC in Window Compare mode requires very little CPU overhead. In our measurements with this circuit, the CPU is active for approximately 12 µs inside the ISR, twice every 8.9 ms. The total CPU overhead is then approximately 0.14 percent. Decreasing the output capacitance will have the effect of requiring more frequent updates, as the output voltage will take less time to charge to the maximum limit, and less time to discharge to the minimum limit.

         

        Below is the circuit with the BOOST pin connected to the MCU:

         

        Circuit with Boost Pin.jpg

         

        And here is with the BOOST pin disconnected:

         

        Pin Disconnected.jpg

         

        The output voltage in this case drops back down to Vin, which is less than required to light the LED.

         

        Switching converters are commonly used in embedded applications to efficiently convert one voltage to another. These switching converters are often controlled by a PWM signal with a varying duty cycle to control the converter’s output characteristics. However, for most MCUs, the ability to generate a PWM signal with a varying duty cycle is limited to relatively low frequencies, which necessitates the use of larger inductors. As an alternative, a high-frequency, fixed-duty-cycle clock output can be used to decrease inductor size, reducing BOM costs and board space requirements.

         

        About the author  

        Brian Lampkin is a microcontroller (MCU) applications engineer at Silicon Labs. He joined the company in 2013 and supports Silicon Labs’ 8-bit and 32-bit MCU products. Brian received a BSEE from Mississippi State University in 2013.

      • IoT Hero Chronicled Breaks Into Another Dimension of User Experience

        deirdrewalsh | 10/278/2016 | 04:34 PM

        We recently enjoyed the chance to chat with Chronicled CEO and co-founder Ryan Orr about his company’s mission to give products a unique, interoperable identity within the IoT realm. Chronicled wants to enable consumers to authenticate their purchases and interact with brands in a manner previously unimaginable.

         

        blog-chronicled.jpg

         

        Can you describe your core business for us? What makes Chronicled special?
        We started out in 2014, starting only with the authentication of high-end sneakers via an embedded smart tag containing pertinent details that could travel with the shoe over its life and help verify it was the genuine article. This year represents a sea change for us, as we have expanded our vision to include tagging most any consumer and luxury item a person buys, making it possible for brands to really engage with those consumers past point of purchase. We’re essentially just taking what we learned with shoes and going bigger, so our product really is now in four parts.

         

        First, we have the smart tag itself on the consumer good—be it a car, a piece of clothing, a piece of furniture, etcetera—and that stores the essential “digital birth certificate” authentication. The tags create a unique identity for the product and make it possible to interact with the product and to experience different kinds of user engagements via a smart phone.

         

        Second is our creation of what we are calling the Open Registry for the IoT; it’s essentially a public data base for all the chips in circulation hosted on Ethereum blockchain. The benefit of using a blockchain as the backend for the Internet of Things is that many different chip companies and brands can register their products there; the blockchain is not controlled by any one company.  Open source tools allow any chip company or brand to register its chips and accompanying products using a registration SDK that ultimately becomes verification SDK to an app. For example, if you’re scanning an $500 purse with your smartphone, you can verify immediately that it’s authentic.

         

        Chronicled_Fakes.png

         

        Thirdly, and where things will get really exciting for developers, is our use of open source code modules, or libraries of apps, if you will. This allows developers to code in exclusive engagement opportunities when people scan goods, extending above a basic authenticity check.  Chronicled is currently working with clients on proximity-based notification, buy-it-now, and social engagement features. For instance, a high-end purse designer could encode exclusive Instagram filters straight from the designer for bag purchasers to access and show off on social media. Or, you could scan a furniture item in a showroom or hotel room and use buy-it-now directly with e-commerce fulfillment from the furniture company.

         

        It’s feels like you are definitely breaking into another dimension of user experience here. You can really start almost “talking” and engaging with these inanimate objects and getting all kinds of social contact from them.
        That’s a good way to put it. Another way to possibly engage is even just wearing your purchase. Proximity is the magic step. If you wear your tagged jeans or are carrying a tagged purse, your smartphone can pick up on that and save that information. And brands will potentially be able to send notifications with iOS 10 to a consumer based on that data, or if you wear multiple versions of the product on the same day, or say the hundredth time that you’ve worn something. The brand will be able to send notifications, a promotion, maybe a social photo filter that says, “Wore my jeans a hundred times,” and you can snap that, save it to your camera roll, and share on your social media. Every time you wear or use your purchase, you are authenticating it and potentially inviting brand interaction. Anyone can buy a knockoff, but the social proof of interaction will help continuously validate authentic purchases.

         

        shoes_purses_stock.jpg

         

        Helping brands provision IoT-equipped products with content  involves the fourth facet of our offering, and that’s what we call our partner portal. Essentially, it gives a company the chance to do their own storytelling. Say you have a winery and they tag 200 bottles of a certain wine vintage that gets bottled one day. They would have the ability to attach information about this special vintage, maybe exclusive video content showing it all being poured in and sealed or an interview with vineyard staff—creating in effect a “digital experience limited edition bottle series,” not just a generic limited edition bottle on a shelf as we have always known it. Companies have a chance to really put their mark on their finished products and connect to that buyer in a way that simply wasn’t possible before the IoT.

         

        Wine_stock.jpg

         

        I can literally hear the elevated heart rates of marketing departments across the world excitedly thinking of how to play with what you’ve done. But tell us, how did you bring the registry to life?
        We actually reviewed 15–20 competing products. And we found that the Blue Gecko BGM111 Bluetooth Smart Module was the best optimization of cost and performance for us. We really liked the packaging of the product with a developer kit. It made it easy to flexibly program and use the chip. And there were security features that we needed and weren’t willing to make trade-offs around.

         

        In your opinion, what does the future of the consumer IoT look like in your mind?
        I think the consumer IoT can be the fourth major technology wave if you think of the first three as the personal computer, the mobile revolution, and then the social revolution. Today, we're at a point where all three of these former technological eras have merged in a single device—the smartphone, an Internet-connected, mobile computer that slides in your pocket.

         

        You probably have two billion people walking around with smartphones, and these devices easily have the functionality to interact with these microchips you can put into anything. So this next era is going to be about interacting with the physical world around you via your smartphone, and maybe soon with your augmented reality glasses. And this fourth consumer wave will be as big as the prior three, with people figuring out how to put chips in things and how to create user engagement experiences that are meaningful and enhance people’s lives. It will be a big wave over the next seven to 10 years.