Jump to content
43oh

CorB

Members
  • Content Count

    288
  • Joined

  • Last visited

  • Days Won

    5

Reputation Activity

  1. Like
    CorB reacted to bluehash in First batch of BoosterPacks - Now @SeeedStudio   
    I'd like to thank TI,Seeed and the designers involved for this first batch @ SeeedStudio. If you are ever ordering from Seeed and need a few boosters, check the following out. Also, don't forget, there always is The 43oh Store.
     

     
    The BluePack - 43oh Bluetooth Launchpad Boosterpack The Locator - 43oh MTK3339 GPS Launchpad Boosterpack Wirefree - 43oh Wizfi210 WiFi Launchpad Boosterpack The Protopad - 43oh Prototyping Launchpad Boosterpack The SMDProtopad - 43oh SMD Prototyping  Launchpad Boosterpack      
     
  2. Like
    CorB reacted to VMM in Another 430 Watch   
    Hello.  I figured I would share a project I've been working on since I borrowed a lot of code from this forum.  It's a small watch using a g2553 and the same OLED display as "The Terminal".  Thanks bluehash for the breakout, RobG and gwdeveloper for code, and others.  

  3. Like
    CorB reacted to oPossum in Is it just me or tonight TI doubled LaunchPad price?   
    http://forum.43oh.com/topic/2481-launchpad-mini-revision-3/
     
    http://forum.43oh.com/topic/2482-3-way-50x50mm-proto-board/
     
    Have been working on a low cost FET for use with those. Couldn't touch the $4.30 price point, but that has ended.
  4. Like
    CorB got a reaction from peawlbral in Launchpaddemo on GLCD (with scrolling graph)   
    Hi,
     
    Find attached code to run the launchpadDemo on the GLCD boosterpack(Lars Roland), The code will show the temperature in tenths of a degree and after pressing Switch2 on the GLCD boosterpack a scrolling graph will show the changes in temperature.
     
    The file called Example_F2802xLaunchPadDemo1.c can be used to replace the original launchpaddemo file. All other files should be copied into the directory where "Example_F2802xLaunchPadDemo" resides.
     
    The graph on the GLCD is is based on graphs writing to a screenmemory that can be dumped to the LCD.
     
    I will add a screenshot tomorrow (EDIT: screenshots added).
     
    cheers
    CorB
    Example_F2802xLaunchPadDemo.zip


  5. Like
    CorB reacted to kenyee in Turn off Bright Green power LED when running MSP430 Launchpad on Battery?   
    Bingo!  :-)
    Specifically, the reset jumper.  I put the test jumper back in w/o problems.  Weird.
     
    ok, so for battery use, connect it to the vcc/gnd/gnd (only one gnd has to be connected to the battery).
    Pull off the vcc/reset jumpers in the block of jumpers in the emulation section.
     
    It's now running happily off a cr2032...
  6. Like
    CorB reacted to larsie in Square wave generator   
    I've coded a very simple square wave generator. It uses the buttons on P1.0 eh... ooopps... PB5 and PB0 (the two first buttons on the LarsLCD board), and prints the kHz value on the LarsLCD. It should run without the LCD also. The output is on PA2 (bottom right).


    The LCD library is from CorB's post and is mainly his code by now. The generator code is adapted from the example timer code in the project documentation. If you have input on ways to write it better (button presses etc), I'm very happy to receive feedback.
     
    #include <stdint.h> #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/ssi.h" #include "driverlib/sysctl.h" #include "driverlib/interrupt.h" #include "driverlib/timer.h" #include "glcd_hwSPI.h" void PortBIntHandler(void); #define SSI_CLK GPIO_PIN_4 #define SSI_TX GPIO_PIN_7 #define GPIO_PB4_SSI2CLK 0x00011002 #define GPIO_PB7_SSI2TX 0x00011C02 volatile int btn1 = 0; int main(void) { unsigned long ulPeriod; SysCtlClockSet( SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_2); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3); SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // CS ENABLE GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5); // CS LOW GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_5, 0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); GPIOPinConfigure(GPIO_PB4_SSI2CLK); GPIOPinConfigure(GPIO_PB7_SSI2TX); GPIOPinTypeSSI(GPIO_PORTB_BASE, SSI_CLK | SSI_TX); // // Configure SSI2 // SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, SysCtlClockGet() / 2, 16); // // Enable the SSI module. // SSIEnable(SSI2_BASE); LCD_Init(); SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER); ulPeriod = (SysCtlClockGet() / 1000) / 2; TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod - 1); IntEnable(INT_TIMER0A); TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); IntMasterEnable(); TimerEnable(TIMER0_BASE, TIMER_A); // Set up IO GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, GPIO_PIN_0); GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_0, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); GPIOPinTypeGPIOInput(GPIO_PORTB_BASE, GPIO_PIN_5); GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_5, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); writeString(0, 0, "Signal generator"); int f = 1; while (1) { int pressed = 0; if (!GPIOPinRead(GPIO_PORTB_BASE, GPIO_PIN_5)) { GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_1); SysCtlDelay(1000000); GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, 0); f -= 1; pressed = 1; } else if (!GPIOPinRead(GPIO_PORTB_BASE, GPIO_PIN_0)) { GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_2); SysCtlDelay(1000000); GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3, 0); f += 1; pressed = 1; } if (pressed) { if (f < 0) { f = 1; } else if (f > 999) { f = 999; } ulPeriod = (SysCtlClockGet() / (f * 1000)) / 2; TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod - 1); } setcharmode(1); writeInt(20, 2, f, 1); setcharmode(0); writeString(70, 3, "kHz"); writeString(0, 7, " - + "); pressed = 0; } } void Timer0IntHandler(void) { // Clear the timer interrupt TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); // Read the current state of the GPIO pin and // write back the opposite state if (GPIOPinRead(GPIO_PORTA_BASE, GPIO_PIN_2)) { GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, 0); } else { GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_2, GPIO_PIN_2); } }   
    Files are attached, including the LCD library. I've adapted it to use header-files.
    sq-wav-gen.zip

  7. Like
    CorB reacted to Thomas1426459898 in SLLogicLogger - A simple logic analyser for the Stellaris Launchpad   
    Hi,
     
    Here is my last project with the Stellaris Launchpad: SLLogicLogger - A simple logic analyser for the TI Stellaris Launchpad.
     
    Logic levels on PORTB are sampled with 10MHz to RAM (16 kBytes) and then transmitted through the debugging controller over USB to a host computer. No additional hardware is needed - a pure Stellaris Launchpad connected over the debug-USB to an PC is enough. The firmware implements the main functions of SUMP, a serial protocol for logic analysers. There are some clients which supports SUMP. I used LogicSniffer OLS (http://www.lxtreme.nl/ols/) which is a multiplatform Java client. A simple OLS profile file is sufficient to read out the sampled data from the Launchpad.
    Sampling starts on any state change on PORTB, no further trigger functions are supported yet.
     
    Further description and download:
    http://www.fischl.de/arm/sllogiclogger_logic_analyser_for_stellaris_launchpad/
     
    The logic states are sampled from the GPIO to an array within an for-loop:
    // sampling buffer char buffer[BUFFERSIZE]; // aquire data for (i = BUFFERSIZE; i != 0; i--) { buffer[i - 1] = GPIO_PORTB_DATA_R; } With this method I get 10 MHz sampling rate at 80 MHz system clock. Does anybody know, if there is a chance to speed it up? E.g. using AHB, uDMA, ...?
     
    Thomas

  8. Like
    CorB reacted to spirilis in MSP430F5172 LaunchPad XL   
    Boards are in, one complete, its XTAL seems to stabilize reliably every time now:

     
  9. Like
    CorB got a reaction from msptest6 in Interrupt based button and PORT_A leds   
    NFC surely looks interesting ... would be even more interesting if we could program devices using NFC ... maybe in the future.
     
    EDIT: ... future might be nearer than I thought, see http://www.ti.com/lit/an/sloa160/sloa160.pdf
     
    Looks like an NFC version of the RFBSL (bootstraploader) has allready been worked out ...
  10. Like
    CorB reacted to larsie in Search length   
    Would it be possible to allow shorter search words? I can't search for PWM for example, since it has to have four characters. 
  11. Like
    CorB got a reaction from larsie in Boosterpack LCD (Lars) on StellarisTI   
    After changing the HW (see previous) to an electret microphone it was time to see if the electret setup can hear high frequencies properly.
    For this I have programmed an MSP430G2553 (launchpad) to simply toggle an IO pin with a delay in between the hi and lo stages. Connected a small 8ohm speaker to that and started testing. I wasnt sure if the speaker would go high enough for my project but it seems it does ... I cant hear anything coming from the speaker but I did see the electret picking up a signal at a constant frequency. Next question was ... how high is the frequency I am producing actually. Ive first turned on my old bat-detector that allows my to tune the receiver to a signal. Turns out there was something like 45Khz coming from the speaker and that 45Khz also was in line with my observations on the spectrumgraphs. Using the spectrum software with a maximum detectable frequency of 60Khz the peak was just over halfway the graph. My batdetector wasnt calibrated recently so it might be slightly off.
     
    Unfortunately there are no real bats around yet but I will probably program the MSP430 to generate a frequency sweeper so I can move to the next stage ... showing an incoming ultrasonic beep as a spectrumgraph captured in time. 
     
    Onwards again !
     
    CorB
     
    EDIT: some pictures
     
    ultrasonic peak (graph shows frequencies 0 -60000Khz)

    ultrasonic peak (graph shows frequencies 0 -80000Khz)

     
    In both graphs you can see some dynamic/static noise on the rightside of the graph. That probably hsa to do with the fact that the whole setup of the microphone/opamp is currently setup on a breadboard.
     
     
  12. Like
    CorB got a reaction from abecedarian in Boosterpack LCD (Lars) on StellarisTI   
    Just changed the HW part of this project based on a simple electret microphone and LM386 opamp scheme from 
    http://lowvoltage.wordpress.com/2011/05/15/lm386-mic-amp/
     
    This allows you to create a very sensitive setup, fingersnaps at 2 meters can be recorded over the spectrum. When I whistle (dont come to listen) I can see very clearly which frequencies I am "misusing". The "kitchentimer" I used for testing (beeps) can be sensed from over several meters away.
     
    Next up is sensing frequencies above 20 Khz since that is my special aim with this project, detecting ultrasonic beeps from bats.
     
    cheers
    CorB
  13. Like
    CorB got a reaction from kstuart in Anaren TI CC110L RF AIR Booster Pack   
    This link shows how I uses packages to send information around:
    http://forum.43oh.com/topic/1433-anaren-ti-cc110l-rf-air-booster-pack/?p=17770
     
    Below a bit more on the secrets You can define the payload any way you wish with any data you want to transfer. As you can see my setup uses ACKs and also nodeIDs but you could do that completely different. The only mandatory thing (at least its wise) is to start with an addr part in your payloadframe since the receivers can check automatically for this. I am using 2 payload variables In_Payload and Out_Payload to do all the exchanges, next to that there are 2 buffers declared for receiving/sending payloads. Makes sure they are large enough.
     
    After receiving a package I use the following code to decipher the package into to In_Payload variable
    LoadRxBuffer((char *)&In_Payload,len); // translate rxBuffferdata into In_Payload
     
    Sending a package is simple, you first set your packagedata in the Out_Payload structure and then call
    send_Msg(xxxx)  where xxxx is a command you want to send around. 
     
    Have fun !
     
    CorB
     
     
     
     
     
    //PAYLOADS typedef volatile struct StatusStruct { enum TxACKMessageType { //!< Flags to ACK transfer REQUEST_NO_ACK = 0, REQUEST_ACK = 1 } TxACKMessageType; enum RxACKMessageType { //!< Flags to ACK transfer RECEIVED_NO_ACK = 0, RECEIVED_ACK = 1 } RxACKMessageType; char channel; char power; char RSSI; unsigned int msgNodeId; } StatusStruct; typedef struct PayloadFrame { char addr; // payloads need to start with char addr as the receiver can check this ! char msg; // messagetype 0x00 - 0xFF options char msgdata0; // var1 that belongs to the message char msgdata1; // var2 that belongs to the message StatusStruct Status; // USER DESIGNED PAYLOAD SECTION unsigned int data1; //unsigned int data2; char DataUnit; } PayloadFrame; PayloadFrame In_Payload; // receiving payload PayloadFrame Out_Payload; // sending payload #define maxPayload 40 // reserve space for the payloadsize in the buffers char txBuffer[maxPayload]; // sizeof(PayloadFrame) !! char rxBuffer[maxPayload]; // this routine sets default settings for payloads that will be send PayloadFrame * DefaultPayload () { Out_Payload.addr=0x01; // force adress Out_Payload.msg=DATA_PAYLOAD; Out_Payload.msgdata0=0; Out_Payload.msgdata1=0; Out_Payload.DataUnit='_'; Out_Payload.Status.RxACKMessageType=RECEIVED_NO_ACK ; Out_Payload.Status.TxACKMessageType= REQUEST_ACK; Out_Payload.Status.msgNodeId=NodeId; return &Out_Payload; } // transfer of a payload PayloadFrame * MakeTxPayload () { Out_Payload.Status.msgNodeId=NodeId; // always enforce ! return &Out_Payload; } // load a payload into the RxBuffer char LoadRxBuffer (char *buffer, char len) { int i = 0; for (i = len; i >= 0; i--) { buffer[i] = rxBuffer[i]; // Recreate Payload from received data } return 0; } // load a payload into the TxBuffer char PreparetxBuffer (char *payload, char len) { int i = 0; for (i = len; i >= 0; i--) { txBuffer[i+1] = payload[i]; // Create DataPacket from Payload } txBuffer[0]=len; // byte 0 in the pack should be the package length return 0; } // Send a payload void send_Msg(char message) { Out_Payload.addr=0x01;//force address Out_Payload.msg=message; PreparetxBuffer( (char *)(MakeTxPayload()), sizeof(PayloadFrame)); RFSendPacket(txBuffer, txBuffer[0]+1); // 1 byte larger than payloadframe due to the packagesize byte __delay_cycles(5000); //5ms waiting }
  14. Like
    CorB got a reaction from EngIP in Anaren TI CC110L RF AIR Booster Pack   
    This link shows how I uses packages to send information around:
    http://forum.43oh.com/topic/1433-anaren-ti-cc110l-rf-air-booster-pack/?p=17770
     
    Below a bit more on the secrets You can define the payload any way you wish with any data you want to transfer. As you can see my setup uses ACKs and also nodeIDs but you could do that completely different. The only mandatory thing (at least its wise) is to start with an addr part in your payloadframe since the receivers can check automatically for this. I am using 2 payload variables In_Payload and Out_Payload to do all the exchanges, next to that there are 2 buffers declared for receiving/sending payloads. Makes sure they are large enough.
     
    After receiving a package I use the following code to decipher the package into to In_Payload variable
    LoadRxBuffer((char *)&In_Payload,len); // translate rxBuffferdata into In_Payload
     
    Sending a package is simple, you first set your packagedata in the Out_Payload structure and then call
    send_Msg(xxxx)  where xxxx is a command you want to send around. 
     
    Have fun !
     
    CorB
     
     
     
     
     
    //PAYLOADS typedef volatile struct StatusStruct { enum TxACKMessageType { //!< Flags to ACK transfer REQUEST_NO_ACK = 0, REQUEST_ACK = 1 } TxACKMessageType; enum RxACKMessageType { //!< Flags to ACK transfer RECEIVED_NO_ACK = 0, RECEIVED_ACK = 1 } RxACKMessageType; char channel; char power; char RSSI; unsigned int msgNodeId; } StatusStruct; typedef struct PayloadFrame { char addr; // payloads need to start with char addr as the receiver can check this ! char msg; // messagetype 0x00 - 0xFF options char msgdata0; // var1 that belongs to the message char msgdata1; // var2 that belongs to the message StatusStruct Status; // USER DESIGNED PAYLOAD SECTION unsigned int data1; //unsigned int data2; char DataUnit; } PayloadFrame; PayloadFrame In_Payload; // receiving payload PayloadFrame Out_Payload; // sending payload #define maxPayload 40 // reserve space for the payloadsize in the buffers char txBuffer[maxPayload]; // sizeof(PayloadFrame) !! char rxBuffer[maxPayload]; // this routine sets default settings for payloads that will be send PayloadFrame * DefaultPayload () { Out_Payload.addr=0x01; // force adress Out_Payload.msg=DATA_PAYLOAD; Out_Payload.msgdata0=0; Out_Payload.msgdata1=0; Out_Payload.DataUnit='_'; Out_Payload.Status.RxACKMessageType=RECEIVED_NO_ACK ; Out_Payload.Status.TxACKMessageType= REQUEST_ACK; Out_Payload.Status.msgNodeId=NodeId; return &Out_Payload; } // transfer of a payload PayloadFrame * MakeTxPayload () { Out_Payload.Status.msgNodeId=NodeId; // always enforce ! return &Out_Payload; } // load a payload into the RxBuffer char LoadRxBuffer (char *buffer, char len) { int i = 0; for (i = len; i >= 0; i--) { buffer[i] = rxBuffer[i]; // Recreate Payload from received data } return 0; } // load a payload into the TxBuffer char PreparetxBuffer (char *payload, char len) { int i = 0; for (i = len; i >= 0; i--) { txBuffer[i+1] = payload[i]; // Create DataPacket from Payload } txBuffer[0]=len; // byte 0 in the pack should be the package length return 0; } // Send a payload void send_Msg(char message) { Out_Payload.addr=0x01;//force address Out_Payload.msg=message; PreparetxBuffer( (char *)(MakeTxPayload()), sizeof(PayloadFrame)); RFSendPacket(txBuffer, txBuffer[0]+1); // 1 byte larger than payloadframe due to the packagesize byte __delay_cycles(5000); //5ms waiting }
  15. Like
    CorB got a reaction from bluehash in Boosterpack LCD (Lars) on StellarisTI   
    Hi,
     
    Find below the adapted code to use the application Jordan Wills has made for usage with the LARS LCD booster. Next to setting up the SPI for the LCD Ive also changed many aspects of the code to my specific needs. According to my knowledge the original FFT usage fo the CMSIS library wasnt exactly as it should be.
    This refers first to the call of arm_cmplx_mag_f32(g_fFFTResult, g_fFFTResult, NUM_SAMPLES) which original was using NUM_SAMPLES*2 as a parameter.
    Secondly it refers to the original code using the full FFT Output to populate the frequency bins. The FFTsize is 2048 for this application, the output after calculation of the powers per frequency bin is half of that so 1024 bins. The data in these bins are however mirrored around the midpoint, so bin [0] is the same as bin[511] and bin[1] equals bin[510]. So in the code below you will see that I am only using the first half of the FFToutput.
    Also not that I am not using the Hamming WIndow as a prefiltering, this might be necessary for other setups but in my current setup it is not.
     
    The code is not yet fully documented but should be working directly ... i hope. To use it you first need to install the original code and then use the new Led_equalizer.c as the main file.
     
    cheers
     
    Cor
     
    //***************************************************************************** // // led_equalizer.c - A project that uses the ADC to capture analog input, the // CMSIS DSP library to analyze that input, and an Olimex 8x8 LED tile to // display the power of 8 logarithmicly spaced frequency ranges. // // Copyright (c) Jordan Wills, aka EuphonistiHack, wills.jordan@gmail.com // For more information, see writeup at // http://www.euphonistihack.blogspot.com/2012/08/the-writeup.html // // adapted for LARS LCD usage by CorB. dec 2012 // // This project was intended to run on a TI LM4F120XL on a Stellaris Launchpad // evaluation kit. It was developed in my free time without using company // resources. As such, feel free to copy and redistribute this code as you see // fit. I politely ask that you only use this code on Texas Instruments // hardware, as it would be frustrating to see my hard work running on a board // manufactured by one of my employer's competitors (I'm lookikng at you, ST // and Freescale). However, my polite request in no way constitutes a legally // enforcable demand, so if you really want to use it on an ST board, I won't // stop you. At least give me some credit in your comments though // // This project contains ABSOLUTELY NO WARRANTY, meaning it does not even have // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. If there's a bug in this code that smokes your board, sorry, but // you're on your own. // //***************************************************************************** #include <string.h> #include "inc/hw_adc.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "driverlib/adc.h" #include "driverlib/debug.h" #include "driverlib/fpu.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/ssi.h" #include "driverlib/sysctl.h" #include "driverlib/systick.h" #include "driverlib/timer.h" #include "driverlib/udma.h" #include "arm_math.h" // ______________________ // | | // VCC |J1.1 J2.1| GND // |J1.2 pb5 pb2 J2.2| // |J1.3 pb0 pe0 J2.3| // |J1.4 pb1 pf0 J2.4| // |J1.5 pe4 xxx J2.5| // glcd-cs |J1.6 pe5 pb7 J2.6|<-------| glcd-MISO // glcd-CLK |J1.7 pb4 pb6 J2.7| // |J1.8 pa5 pa4 J2.8| // |J1.9 pa6 pa3 J2.9| // |J1.10 pa7 pa2 J.210| // | | // ---------------------- // ______________________ // | | // |J3.1 VBUS pf2 J4.1| // |J3.2 GND pf3 J4.2| // |J3.3 pd0 pb3 J4.3| // |J3.4 pd1 pc4 J4.4| // |J3.5 pd2 pc5 J4.5| // |J3.6 pd3 pc6 J4.6| // |J3.7 pe1 pc7 J4.7| // |J3.8 pe2 pd6 J4.8| // IN ->> |J3.9 pe3 pd7 J4.9| // |J3.10 pf1 pf4 J4.10| // | | // ---------------------- //***************************************************************************** //! This project uses the following peripherals and pins: //! ADC input 0 for audio capture //! SSI2 for communication with the LARS LCD //! // Hardware conditioning circuit // BUS J3 // AIN = PE3 - AIN0 // // BUS J1 // Pin 1 - Vcc = J1[1] - VBUS // Pin 6 - SR_LATCH = PE5 - GPIO // Pin 7 - SR_SCK = PB4 - SSI2Clk // // BUS J2 // Pin 1 - GND = J1[2] - GND // Pin 6 - SR_DATA_IN = PB7 - SSI2Tx // CORRECTED BY CORB // //***************************************************************************** //***************************************************************************** // // Preprocessor directives // //***************************************************************************** // // The error routine that is called if the driver library encounters an error. // #ifdef DEBUG void __error__(char *pcFilename, unsigned long ulLine) { } #endif //***************************************************************************** // // SSI and display macros // //***************************************************************************** // // audio sampling frequency = 2 * Nyquist = 2 * 22.3 kHz = 44600 // #define SAMPLING_FREQ 44600 // Number of samples to capture for each FFT process. Set to CMSIS max for // best resolution // #define NUM_SAMPLES 2048 #define FFTSIZE 2048 #define DISPLAYFFT FFTSIZE/4 // // REFRESH THE DISPLAY, HIGHER IS MORE FREQUENT #define REFRESH_RATE 1000 //LCD COMMANDS #define DATA 0x01 #define CMD 0x00 #define DISPLAYWIDTH 96 //DISPLAY SETUP #define HORZ 0 #define VERT 1 #define SCREENDIR VERT // horizontal display 8 frequencybins #if SCREENDIR==HORZ #define DISPLAYMAX 96 #define NUM_F_BINS 8 #endif // vertial display up to 94 frequencybins #if SCREENDIR==VERT #define DISPLAYMAX 64 #define BIN_PIXELS 10 #define NUM_F_BINS (DISPLAYWIDTH-2)/BIN_PIXELS #endif // Pins used for SSI interface // #define SSI_CLK GPIO_PIN_4 #define SSI_TX GPIO_PIN_7 //***************************************************************************** // // Audio capture and signal processing macros // //***************************************************************************** // // The ADC sequencer to be used to sample the audio signal // #define ADC_SEQUENCER 3 // // Flag used to determine whether to calculate forward (0) or inverse(1) fft // #define INVERT_FFT 0 // // Flag used to determine if fft result will be output in standard bit order(1) // or reversed bit order (0) // #define BIT_ORDER_FFT 1 // // The maximum number of transfers one UDMA transaction can complete // #define UDMA_XFER_MAX 1024 //***************************************************************************** // // Global variables // //***************************************************************************** // // The control table used by the uDMA controller. This table must be aligned // to a 1024 byte boundary. // #if defined(ewarm) #pragma data_alignment=1024 unsigned char ucControlTable[1024]; #elif defined(ccs) #pragma DATA_ALIGN(ucControlTable, 1024) unsigned char ucControlTable[1024]; #else unsigned char ucControlTable[1024] __attribute__ ((aligned(1024))); #endif void SPIWrite(uint16_t command, uint16_t data) { uint16_t spidata; spidata = command<<15; spidata = spidata | data <<7; SSIDataPut(SSI2_BASE, spidata); // // Wait until SSI is done transferring all the data in the transmit FIFO // while(SSIBusy(SSI2_BASE)) { } // // Hit the SSI latch, locking in the data // GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_5, GPIO_PIN_5); GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_5, 0); } void setCursor(unsigned char column, unsigned char line) // position in pixels to the LCD-writeposition at a byte { column = (column % DISPLAYWIDTH); //line = (line % (height/9 + 1)); line = (line %9); SPIWrite(CMD, 0x80 | column); SPIWrite(CMD, 0x40 | line); } // display vertical line at position X with length=value void Vbar(char x, char value) { volatile char y; char line,bit; char lines[8]; for (y=0; y<8; y++) { lines[y]=0; } x=x*BIN_PIXELS; // set bits for (y=64; y>64-value; y--) { line=y/8; bit=(1<<(y%8)); lines[line] |= (bit); } // display bar for (y=0; y<8; y++) { SPIWrite(CMD, 0x80 | x); SPIWrite(CMD, 0x40 | y); for (line=0; line<BIN_PIXELS; line++) { SPIWrite(DATA,lines[y]); } } } // erase LCDscreen and screenmemory void clear() { int i,j; SPIWrite(CMD, 0x80); // set cursor at beginning SPIWrite(CMD, 0x40); for (i = 0; i < 9; i++) { for ( j = 0; j < 102; j++) { SPIWrite(DATA, 0x01); } } setCursor(0, 0); } void LCD_Init() { SPIWrite(CMD, 0x21); //Function set PD=0,H1=0,H0=1 SPIWrite(CMD, 0x10+0x03); //SET Bias system SPIWrite(CMD, 0X80+0x20); //SET V0 SPIWrite(CMD, 0x20); //Function set PD=0 ,H1=0, H0=0 SPIWrite(CMD, 0x05); //Set VLCD Range(PRS) 0x04 = VLo-low, 0x05 VO-high SPIWrite(CMD, 0x0C); //Display control D=1 E=0 (Normal) 0x0C = normal display 0x0D = reversed SPIWrite(CMD, 0x40); //Set Y startingline BIT6 line0=0x40 SPIWrite(CMD, 0x80); //Set y startingline BIT5-0 line0=0x80 SPIWrite(CMD, 0x28); //Function set PD=0,H1=0,H0=0 reverse directions clear(); // clear the screen } // // The ADC storage array // unsigned long g_ulADCValues[NUM_SAMPLES]; float32_t g_fFFTResult[NUM_SAMPLES * 2]; // // FFT and CMSIS config structures // arm_rfft_instance_f32 fftStructure; arm_cfft_radix4_instance_f32 cfftStructure; // // Hamming window, used to prepare samples for fft and correct for the fact // we're using an algorithm meant for a continuous, infinite signal on a // signal that is finite and not always continuous. // extern float ti_hamming_window_vector[NUM_SAMPLES]; // // The range in Hertz of each frequency bin // float g_HzPerBin; // // Flag from the uDMA engine signaling that data is ready to be processed // volatile unsigned char g_ucDataReady=0; // // The count of uDMA errors. This value is incremented by the uDMA error // handler. // static volatile unsigned long g_uluDMAErrCount = 0; // // The count of times various uDMA error conditions detected. // static volatile unsigned long g_ulBadPeriphIsr1 =0; // CHANGED CORB static volatile unsigned long g_ulBadPeriphIsr2 =0; // CHANGED CORB // // The character array used to update the LED display // static float32_t LEDPower[NUM_F_BINS]; unsigned int LEDDisplay[NUM_F_BINS]; unsigned int LEDFreqBreakpoints[NUM_F_BINS + 1]; //***************************************************************************** // // Private function declarations // //***************************************************************************** //***************************************************************************** // // The interrupt handler for Timer0A. Originally, this was used to display // debug information once per second. Keeping this around for debug, but in // the final system, this isn't necessary, as ADC capture is triggered at the // HW level, alleviating the need for a software interrupt handler to trigger. // //***************************************************************************** void Timer0AIntHandler(void) { // Clear the timer interrupt. // TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); } //***************************************************************************** // // The interrupt handler for Timer1A. Used for refreshing the LED display. // //***************************************************************************** void Timer1AIntHandler(void) { unsigned long ulData; static unsigned char ucLED = 0; // // Clear the timer interrupt. // TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT); ulData = LEDDisplay[ucLED]; // check for display overflows if (ulData>DISPLAYMAX) {ulData=DISPLAYMAX;} #if SCREENDIR==HORZ setCursor(0,ucLED); char i; for (i = 0; i < ulData; i++) { SPIWrite(DATA, 0xFF); } for (i=ulData; i< DISPLAYMAX; i++) { SPIWrite(DATA, 0x00); } #endif #if SCREENDIR==VERT Vbar(ucLED,ulData); #endif // // Move on to the next display element // ucLED++; if(ucLED >= NUM_F_BINS) { ucLED = 0; } // // Reset the timer to trigger again on the next refresh cycle // TimerLoadSet(TIMER1_BASE, TIMER_A, SysCtlClockGet()/REFRESH_RATE); TimerEnable(TIMER1_BASE, TIMER_A); } //***************************************************************************** // // The interrupt handler for the ADC sequencer used to capture all audio data. // This handler is called each time the uDMA completes a full ADC->memory copy. // Yes, that's a bit confusing... the uDMA interrupt is only triggered when the // uDMA behaves abnormally. When the uDMA engine completes its transfer, it // calls the interrupt of whatever module fed it the data, not the uDMA // interrupt. // //***************************************************************************** void ADC3IntHandler(void) { unsigned long ulStatus; static unsigned long uluDMACount = 0; static unsigned long ulDataXferd = 0; unsigned long ulNextuDMAXferSize = 0; // // Clear the ADC interrupt // ADCIntClear(ADC0_BASE, 3); // // Disable the sampling timer // TimerDisable(TIMER0_BASE, TIMER_A); // // If the channel's not done capturing, we have an error // if(uDMAChannelIsEnabled(UDMA_CHANNEL_ADC3)) { g_ulBadPeriphIsr2++; ADCIntDisable(ADC0_BASE, 3); IntPendClear(INT_ADC0SS3); return; } // // Verify count remaining is 0. // ulStatus = uDMAChannelSizeGet(UDMA_CHANNEL_ADC3); if(ulStatus) { g_ulBadPeriphIsr1++; return; } // // If our sample size can be greater than our maximum uDMA transfer // size, we might need to set up another uDMA transfer before signaling // that we are ready to process the data. // uluDMACount++; ulDataXferd += UDMA_XFER_MAX; if(NUM_SAMPLES > ulDataXferd) { // // Figure out how many more uDMA transfers are required to completely // fill our sample array, which will tell us what size we need our next // uDMA transfer to be // if((NUM_SAMPLES - ulDataXferd) > UDMA_XFER_MAX) { ulNextuDMAXferSize = UDMA_XFER_MAX; } else { ulNextuDMAXferSize = NUM_SAMPLES - ulDataXferd; } uDMAChannelTransferSet(UDMA_CHANNEL_ADC3 | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)(ADC0_BASE + ADC_O_SSFIFO3 + (0x20 * UDMA_ARB_1)), g_ulADCValues + (UDMA_XFER_MAX * uluDMACount), ulNextuDMAXferSize); uDMAChannelEnable(UDMA_CHANNEL_ADC3); TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet()/(SAMPLING_FREQ - 1)); TimerEnable(TIMER0_BASE, TIMER_A); } else { // // Since this transfer is now done, disable the interrupt so the // handler is not called any more until set up again. Also need // to unpend in case it happened again since we entered this // handler // uluDMACount = 0; ulDataXferd = 0; ADCIntDisable(ADC0_BASE, 3); IntPendClear(INT_ADC0SS3); g_ucDataReady = 1; } } //***************************************************************************** // // The interrupt handler for uDMA errors. This interrupt will occur if the // uDMA encounters a bus error while trying to perform a transfer. Hopefully, // this code will never be executed. // //***************************************************************************** void uDMAErrorHandler(void) { unsigned long ulStatus; // // Check for uDMA error bit // ulStatus = uDMAErrorStatusGet(); // // If there is a uDMA error, then clear the error and increment // the error counter. // if(ulStatus) { uDMAErrorStatusClear(); g_uluDMAErrCount++; } } //***************************************************************************** // // Initialize the signal capture chain. // ADC is initialized to capture based on the sampling timer // uDMA is set up to transfer the samples from the ADC to the global sample // array each time a sample is captured by the ADC. // // The end result is a very efficient, 90% hardware handled process in which // the software says "give me a sample" and the hardware interrupts a short // time later with the data nicely arranged in a convenient location. I'm not // gonna lie... this is pretty awesome. // //***************************************************************************** void InitADC3Transfer(void) { unsigned int uIdx; g_ucDataReady = 0; // // Init buffers // for(uIdx = 0; uIdx < NUM_SAMPLES; uIdx++) { g_ulADCValues[uIdx] = 0; } // // Configure and enable the uDMA controller // SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); IntEnable(INT_UDMAERR); uDMAEnable(); uDMAControlBaseSet(ucControlTable); // // Configure the ADC to capture one sample per sampling timer tick // SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralReset(SYSCTL_PERIPH_ADC0); ADCSequenceConfigure(ADC0_BASE, ADC_SEQUENCER, ADC_TRIGGER_TIMER, 0); ADCSequenceStepConfigure(ADC0_BASE, ADC_SEQUENCER, 0, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END); // // Enable the sequencer // ADCSequenceEnable(ADC0_BASE, ADC_SEQUENCER); ADCIntEnable(ADC0_BASE, ADC_SEQUENCER); // // Configure the DMA channel // uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC3, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); uDMAChannelControlSet(UDMA_CHANNEL_ADC3 | UDMA_PRI_SELECT, UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 | UDMA_ARB_1); // // The uDMA engine has an upper limit of the number of transfers it can // complete before it must be configured for a new transfer. As a result, // we need to configure the uDMA engine to transfer as many samples as // possible, up to its maximum amount // if(NUM_SAMPLES > UDMA_XFER_MAX) { uDMAChannelTransferSet(UDMA_CHANNEL_ADC3 | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)(ADC0_BASE + ADC_O_SSFIFO3 + (0x20 * UDMA_ARB_1)), g_ulADCValues, UDMA_XFER_MAX); } else { uDMAChannelTransferSet(UDMA_CHANNEL_ADC3 | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)(ADC0_BASE + ADC_O_SSFIFO3 + (0x20 * UDMA_ARB_1)), g_ulADCValues, NUM_SAMPLES); } // // Enable the DMA channel // uDMAChannelEnable(UDMA_CHANNEL_ADC3); } //***************************************************************************** // // Initialize basic stuff: // processor // UART0(debug) // //***************************************************************************** void InitBasics(void) { // // Enable lazy stacking for interrupt handlers. This allows floating-point // instructions to be used within interrupt handlers, but at the expense of // extra stack usage. // ROM_FPULazyStackingEnable(); // // Set the clocking to run directly from the crystal. // ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); // // Initialize the UART. // // // Hello! // } //***************************************************************************** // // Initialize the SSI interface used to communicate with the Olimex LED panel // Originally, I was using the software SSI lib to do this, hence the HW in the // name. // //***************************************************************************** void InitHWSSI() { // // Initialize the 3 pins we will need for SPI communication with the LCD // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // connect CS to pin E5 GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5); GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_5, 0); // Connect SPI to PB4 (clock) and PB7(TX) ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); GPIOPinConfigure(GPIO_PB4_SSI2CLK); GPIOPinConfigure(GPIO_PB7_SSI2TX); GPIOPinTypeSSI(GPIO_PORTB_BASE, SSI_CLK | SSI_TX); // // Configure SSI2 // SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, SysCtlClockGet()/2, 16); // // Enable the SSI module. // SSIEnable(SSI2_BASE); // initialize the LCD LCD_Init(); } //***************************************************************************** // // Initialize the timer that will trigger the ADC captures // Timer0 @ 44.6k kHz (macro'd) sampling frequency // //***************************************************************************** void InitSamplingTimer() { // // Set up timer0A to be a one shot that interrupts at 44.6kHz // Set up timer1A to be a 32 bit timer that interrupts at 1/sec // SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); TimerControlTrigger(TIMER0_BASE, TIMER_A, true); TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet()/(SAMPLING_FREQ - 1)); IntEnable(INT_TIMER0A); TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); TimerEnable(TIMER0_BASE, TIMER_A); } //***************************************************************************** // // Initialize the timer that will cause the LED display to refresh // Timer1 @ 1 kHz (macro'd) refresh rate (1 column per refresh) // //***************************************************************************** void InitDisplayTimer() { // // Set up timer1A to be the display timer, interrupting at 15 Hz // SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1); TimerConfigure(TIMER1_BASE, TIMER_CFG_ONE_SHOT); TimerLoadSet(TIMER1_BASE, TIMER_A, SysCtlClockGet()/REFRESH_RATE); IntEnable(INT_TIMER1A); TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT); TimerEnable(TIMER1_BASE, TIMER_A); } //***************************************************************************** // // Initialize the digital signal processing engine. // //***************************************************************************** void InitDSP(void) { volatile int i; // // set our frequency range breakpoints // TODO: we generate all of these with a separate generic algorithm; why // don't we just put that algorithm in here and calculate these values on // init? // char steps=(DISPLAYFFT)/(NUM_F_BINS); // automatically calculate the breakpoints based on the number of frequency bins. i=0; while (i<NUM_F_BINS+1) { LEDFreqBreakpoints[i] = 1+steps*i; i++; } // // Call the CMSIS real fft init function // arm_rfft_init_f32(&fftStructure, &cfftStructure, FFTSIZE, INVERT_FFT, BIT_ORDER_FFT); g_HzPerBin = (float)SAMPLING_FREQ / (float)NUM_SAMPLES; } //***************************************************************************** // // Run the DSP calculations on the input vector. // // Step 1: multiply vector by hamming window // Step 2: get fast fourier transform of samples // Step 3: get complex power of each element in fft output // Step 4: calculate average power in each LED range of bins // Step 5: compare to previously observed maximum power, and set global LED // array for that LED column accordingly // Step 5: ??? // Step 6: Profit // //***************************************************************************** void ProcessData(void) { uint32_t i; uint32_t j; float32_t power,powerhi; volatile float32_t maxValue; uint32_t dummy; // // Ugly, ugly, ugly part where we have to move the ul samples into a float // array because the fixed point fft functions in CMSIS seem to be not // working. While we're at it, we might as well center the samples around // 0, as the CMSIS algorithm seems to like that. // for(i=0;i<NUM_SAMPLES;i++) { g_fFFTResult[i] = ((float)g_ulADCValues[i] - (float)0x800); } // if you want you can Multiply samples by a hamming window, not used by CORB // //arm_mult_f32(g_fFFTResult, ti_hamming_window_vector, g_fFFTResult, NUM_SAMPLES); // Calculate FFT on samples // arm_rfft_f32(&fftStructure, g_fFFTResult, g_fFFTResult); // Calculate complex power of FFT results // arm_cmplx_mag_f32(g_fFFTResult, g_fFFTResult, NUM_SAMPLES); // CORB:CODE CHANGED was NUM_SAMPLES*2 // set max to 100000 to avoid div by zero and too exagerated display of lower values when only lowpower noise is coming in maxValue=100000; // Calculate power stored in the frequency band each LED represents // j = LEDFreqBreakpoints[0]; for(i=1;i<NUM_F_BINS + 1;i++) { // // Find the maximum power of all the LED bins in the freq array. j is // the index of the lowest bin used for this LED. To get the size of // range to take the average of, we do highest indexed bin, // LEDfreqBreakPoints[i], minus the lowest indexed bin, j, + 1. // arm_max_f32(g_fFFTResult+j, LEDFreqBreakpoints[i]-j+1, &powerhi, &dummy); // other functions //arm_mean_f32(g_fFFTResult+j, LEDFreqBreakpoints[i]-j + 1, &powerhi); //arm_min_f32(g_fFFTResult+j, LEDFreqBreakpoints[i]-j+1, &powerlo, &dummy); power=powerhi; //estimate the maximum peak excepting the 1st bin if ((i>1)&&(power>maxValue)) { maxValue=power; } LEDPower[i - 1] = power; j = LEDFreqBreakpoints[i] + 1; } // // Update the LED Display array based on how much power is in the band for // each LED // for(i=0;i<NUM_F_BINS;i++) { // // Normalize currently observed power by maximum observed power LEDDisplay[i] = (unsigned int)(LEDPower[i] / maxValue * DISPLAYMAX); } // // Clear the data ready bit and set up the next DMA transfer // g_ucDataReady = 0; if(NUM_SAMPLES > UDMA_XFER_MAX) { uDMAChannelTransferSet(UDMA_CHANNEL_ADC3 | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)(ADC0_BASE + ADC_O_SSFIFO3 + (0x20 * UDMA_ARB_1)), g_ulADCValues, UDMA_XFER_MAX); } else { uDMAChannelTransferSet(UDMA_CHANNEL_ADC3 | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)(ADC0_BASE + ADC_O_SSFIFO3 + (0x20 * UDMA_ARB_1)), g_ulADCValues, NUM_SAMPLES); } // // Enable the timer and start the sampling timer // uDMAChannelEnable(UDMA_CHANNEL_ADC3); TimerLoadSet(TIMER0_BASE, TIMER_A, SysCtlClockGet()/(SAMPLING_FREQ - 1)); TimerEnable(TIMER0_BASE, TIMER_A); } //***************************************************************************** // // The main function. DO EVERYTHING. // //***************************************************************************** void main(void) { // // Initialize all peripherals // InitBasics(); InitDSP(); InitHWSSI(); InitSamplingTimer(); InitDisplayTimer(); InitADC3Transfer(); // // Once ADC3 interrupts are enabled, our capture engine will start churning // IntEnable(INT_ADC3); while(1) { // // TODO: Figure out how processor sleeping works and add a sleep here. // We only take action after an interrupt occurs anyway, so there's no // sense in sitting here polling a flag that gets set in an interrupt // if we can instead just sleep until an interrupt occurs. // //CPUwfi(); // // Make sure uDMA hasn't exploded // if(g_ulBadPeriphIsr1 || g_ulBadPeriphIsr2) { while(1); } // // If we have new audio data, handle it // if(g_ucDataReady) { ProcessData(); } } }  
     
  16. Like
    CorB got a reaction from bluehash in Boosterpack LCD (Lars) on StellarisTI   
    Hi,
     
    Adding an empty while loop at the end of the main() routine seems to have cleared this issue. Onwards !
     
    Cor
  17. Like
    CorB reacted to RobG in LCD Touch Panel with MSP based GPU   
    This is my second attempt at creating LCD panel with GPU (inspired by CorB.) It's intended use is home automation.
    I will use a 3.0" or 3.2" LCD Touch Panel, MSP430F51x[1,2] based GPU/controller, plus optional LaunchPad headers.
     
    I am still trying to decide which LCD to use (they all cost ~$16.)
     
    3.2", 240x400, 48mm x 81mm, HX8352-A
    3.2", 240x320, 53mm x 75mm, SSD1289Z
    3.0", 320x480, 50mm x 76mm, HX8357-A
    3.0", 240x400, 45mm x 77mm, SPFD5420
     
    Also, I am hoping that the software will become a group effort.
     
    Suggestions?
     

  18. Like
    CorB got a reaction from larsie in Boosterpack LCD (Lars) on StellarisTI   
    Hi,
     
    Ive started to port the code Lars and I have made for the MSP430 and C2K now also to the StellarisTI Launchpad. Based on a test using the code from Euphonistichack's frequency analyzer I created a simple new project. You can see the code below, however when I tried compiling this I got a load of errors (see the 2nd section). Its unclear to me why this happens as the necessary libraries are linked and the linkpaths are also working as planned. 
     
    I allready saw the initial problems when I was using the original code: GPIOPinConfigure(GPIO_PB4_SSI2CLK);
    This refers to a function in gpio.h and a define in pin_map.h. Without declaring GPIO_PB4_SSI2CLK as a define in the program itself the compiler did not work.
     
    Well here's the full list of issues reported,anybody with a clue ??
     
    cheers
    Cor
    P.S I am sure this is a user problem. Never made a project for the stellaris.
     
    Errors reported:
    undefined first referenced symbol in file --------- ---------------- GPIOPinConfigure ./hello.obj GPIOPinTypeGPIOOutput ./hello.obj >> Compilation failure GPIOPinTypeSSI ./hello.obj GPIOPinWrite ./hello.obj SSIBusy ./hello.obj SSIConfigSetExpClk ./hello.obj SSIDataPut ./hello.obj SSIEnable ./hello.obj SysCtlClockGet ./hello.obj SysCtlClockSet ./hello.obj SysCtlPeripheralEnable ./hello.obj error #10234-D: unresolved symbols remain  
     
     
    Code
    #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/ssi.h" #include "driverlib/sysctl.h" #include "inc/glcd_hwSPI.c" #define SSI_CLK GPIO_PIN_4 #define SSI_TX GPIO_PIN_7 #define GPIO_PB4_SSI2CLK 0x00011002 #define GPIO_PB7_SSI2TX 0x00011C02 int main(void) { SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // CS ENABLE GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5); // CS LOW GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_5, 0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); GPIOPinConfigure(GPIO_PB4_SSI2CLK); GPIOPinConfigure(GPIO_PB7_SSI2TX); GPIOPinTypeSSI(GPIO_PORTB_BASE, SSI_CLK | SSI_TX); // // Configure SSI2 SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, SysCtlClockGet()/2, 16); // // Enable the SSI module. SSIEnable(SSI2_BASE); // initialize the LCD and write a few strings LCD_Init(); writeString(0,0,"LARS LCD"); writeString(0,1,"Test"); }  
     
     
  19. Like
    CorB got a reaction from bluehash in Boosterpack LCD (Lars) on StellarisTI   
    Hi.
     
    Find attached the current testcode. A CCS5.3 project (Larslcd.zip) and 2 glcd_xxx files that need to be put inside the inc directory of stellarisware (or anywhere else if you change the links in the project).
     
     
    LarsLCD.zipglcd_charsets.cglcd_hwSPI.c
     
    This works OK, the stellaris runs the code but the debugger is disabled after the upload.
     
    cheers
     
    CorB
     
  20. Like
    CorB reacted to bluehash in Boosterpack LCD (Lars) on StellarisTI   
    Did you add your driver lib to the linker settings as shown below? Path will change depending on your PC.
     

  21. Like
    CorB got a reaction from bluehash in Frequency analyzer built from the new Stellaris Launchpad   
    Thumbs up for this board !! Using the SPI was (at least compared to the time spend trying on the C2K platform) on the Lars' LCD really simple. PORT E_pin5 is the CS line and the other lines (CLK and TX) are the same as in the original code.
     
    The initialisation of the SPI for Lars' LCD is:
    void InitHWSSI() { // // Initialize the pins we will need for communication with the LCD over SPI // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // CS ENABLE GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5); // CS LOW GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_5, 0); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); GPIOPinConfigure(GPIO_PB4_SSI2CLK); GPIOPinConfigure(GPIO_PB7_SSI2TX); GPIOPinTypeSSI(GPIO_PORTB_BASE, SSI_CLK | SSI_TX); // // Configure SSI2 // SSIConfigSetExpClk(SSI2_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, SysCtlClockGet()/2, 16); // // Enable the SSI module. // SSIEnable(SSI2_BASE); }  
     
     
    The new SPIWrite Routine to write to the LCD looks like this (in library glcd_hwSPI).
    void SPIWrite(uint16_t command, uint16_t data) { uint16_t spidata; spidata = command<<15; spidata = spidata | data <<7; SSIDataPut(SSI2_BASE, spidata); // // Wait until SSI is done transferring all the data in the transmit FIFO // while(SSIBusy(SSI2_BASE)) { } // // Hit the SSI latch, locking in the data // GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_5, GPIO_PIN_5); GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_5, 0); } Everything thusfar seems to work, next up is to get the original output ment for the 8x8 Olimex boosterpack working for the LCD. Easy implementation will be to create 8 bars on the LCD that show the incoming audio.
     
    cheers
    CorB
     
    PS: Since I do not want to disturb the original posters topic Ive created a new topic specific for the LCD
  22. Like
    CorB reacted to oPossum in Bit-Bang USB on MSP430G2452   
    It works!  Unfracking believable - the mouse is moving across the screen!
     
    Have some cleanup to do before posting the code.
  23. Like
    CorB got a reaction from bluehash in Frequency analyzer built from the new Stellaris Launchpad   
    Hi
     
    CCS5.3 installed and I have started working on the code. I see that the Olimex boosterpack uses the same convention as Lars's LCD, it uses SPI and uses MSP430 pin 1.4 = Stellaris J1.6 as the CS pin it seems.
     
    Reading through the documentation of the LED_equalizer code I saw this:
     
      //  Olimex J1 //  Pin 1 - Vcc = J1[1] - VBUS //  Pin 6 - SR_LATCH = PA4 - GPIO //  Pin 7 - SR_SCK      = PB4 - SSI2Clk // //  Olimex J2 //  Pin 1 - GND = J1[2] - GND //  Pin 7 - SR_DATA_IN  = PB7 - SSI2Tx   According to me this isnt par with the documentation of the Stellaris launchpad:   PIN J1.6 on Stellaris is not PA4 but PE5 and PIN J2.7 isnt SSI2Tx, so you probably are using J2.6 which is PB7 and SSI2Tx.   Can you confirm this ?   For ease of use Ive put a template below I will be using to keep track of the connections I am using for the launchpad. This often is easy when checking an old piece of code with HW attached.   //             ______________________ //            |                      | //       VCC  |J1.1              J2.1| GND //            |J1.2  pb5   pb2   J2.2| //            |J1.3  pb0   pe0   J2.3| //            |J1.4  pb1   pf0   J2.4| //            |J1.5  pe4   xxx   J2.5| //  glcd-cs   |J1.6  pe5   pb7   J2.6|<-------| glcd-MISO //  glcd-CLK  |J1.7  pb4   pb6   J2.7|------->| glcd-SOMI //            |J1.8  pa5   pa4   J2.8| //            |J1.9  pa6   pa3   J2.9| //            |J1.10 pa7   pa2  J.210| //            |                      | //             ----------------------     cheers CorB          
  24. Like
    CorB got a reaction from abecedarian in Frequency analyzer built from the new Stellaris Launchpad   
    Hi Euphonistichack,
     
    Thanks for answering. I am using a pre-amp scheme I have used before for a heterodyne batdetector. Nothing excotic, Options are to use a 40khz ultrasonic transducer (ive used those sucessfully) or to use an electret micro with some additional filtering. Theres many schemes around.
     
    I wont need that many bins in the FFT as I am planning to display the data directly on an LCD and a resolution of 1 bin/khz would deliver enough information to determine the species by. Recording data is indeed not easy unless I would simply store the "footprint" with the data /bin. 
     
    Thanks for confirming the possibility to use the stellaris to do this.
     
    cheers
    CorB
  25. Like
    CorB reacted to username in simple wireless link board   
    Hey all, been busy with stupid school so haven't had a chance to post anything recently.
     
    Wanted to put my coffee maker on my own routine schedule so I developed a small wireless board to go in my coffee maker that would simulate button presses / read current statuses. Very basic but handy for controlling appliances that rely on 5V-3.3V logic like my coffee maker. This board just sits inside the coffee maker. I got a control board that this board interfaces to via wireless.
     
    Specs / Features:
    1x NRF24L01 wireless module, *Note they are less than 2.5 USD apice, very cheap. This guy goes on the bottom of the PCB.
    http://www.ebay.com/itm/2pcs-NRF24L01-2-4GHz-Antenna-Wireless-Transceiver-Module-For-Microcontr-/251044600998?pt=LH_DefaultDomain_0&hash=item3a736c9ca6
    2x Digital Inputs
    2x LSD Outputs
    1x RGB LED
    1x MSP430G2553
     
     
    Picture:
     


    Bet you can't guess who made the PCB =P
×
×
  • Create New...