Jump to content
43oh

jsolarski

Members
  • Content Count

    568
  • Joined

  • Last visited

  • Days Won

    8

Reputation Activity

  1. Like
    jsolarski reacted to yyrkoon in MAX31855 based reflow oven controller   
    Software so far initializes SPI, UART, and the max device. Asks the user to press a key ( serial terminal ), then based on table values starts counting down from the duration entry to 0. For each stage. All the while displaying formatted data over serial UART to the PC.
     
    Things yet to implement:
     
    LCD initialization / usage
    button trap detection
    heating elements toggling code 
    fan toggling
    LED toggling
    temperature comparison ( probe temp vs target temp, and controller temp vs a  shutdown threshold ).
     
    Example of formatted test output over UART-> Serial thus far.
     

  2. Like
    jsolarski reacted to sirri in humor: iran space program   
    look at the photo. do you think it is launchpad powered? : )
     
     

  3. Like
    jsolarski reacted to The Chilango power in MSP430 and LCD16X2 My first project   
    Hola les muestro mi primer proyecto con MSP430 LaunchPad es un simple LCD 16X2


     

    #include #include "LCD_v1.h" #define LED1 BIT0 #define LED2 BIT6 #define B1 BIT3 //void setup(void); unsigned char i; typedef char* cadena; int main(void) { cadena string; WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer BCSCTL1 = CALBC1_1MHZ; // Set range DCOCTL = CALDCO_1MHZ; P1REN = 0x00; P1SEL = 0x00; P1IE = 0x00; Inicializa_LCD(); while(1){ Comando_LCD(CLEAR); Dato_String_LCDEx(LN1," HOLA MUNDO "); Dato_String_LCDEx(LN2, " **MSP430** "); delay_ms(2000); Comando_LCD(CLEAR); Dato_String_LCDEx(LN1," HECHO POR "); Dato_String_LCDEx(LN2,"=> THE CHILANGO POWER"); for(i = 0;i < 8;i++){ Comando_LCD(SHIFT_DISP_RIGHT); delay_ms(400); } for(i = 0;i < 14;i++){ Comando_LCD(SHIFT_DISP_LEFT); delay_ms(400); } delay_ms(2000); string = "MSP430 LaunchPad "; Comando_LCD(CLEAR); while(*string){ Dato_LCD(*string++); delay_ms(300); } string = "DATE 27/08/2012"; GoToXY(2,1); while(*string){ Dato_LCD(*string++); delay_ms(300); } delay_ms(1000); for(i=0;i<5;i++){ Comando_LCD(DOFF); delay_ms(200); Comando_LCD(DON); delay_ms(200); } Comando_LCD(DON); delay_ms(1500); } }
     

    /* * LCD_V1.c * * Created on: 13/08/2012 * Author: THE CHILANGO POWER */ #include "LCD_V1.h" //********************************************************** /* Inicializacion del LCD segun fabricante */ //********************************************************** void Inicializa_LCD(void){ PDIR_LCD = 0; POUT_LCD = 0; delay_ms(100); PDIR_LCD |= PDIR_BIT1_LCD | PDIR_BIT2_LCD | PDIR_BIT3_LCD | PDIR_BIT4_LCD; PDIR_LCD |= PDIR_PIN_RS | PDIR_PIN_E; POUT_LCD &= ~POUT_PIN_E; POUT_LCD &= ~POUT_PIN_RS; Flex_port(0X03); POUT_LCD |= POUT_PIN_E; delay_us(1); POUT_LCD &= ~POUT_PIN_E; delay_ms(5); Flex_port(0X03); POUT_LCD |= POUT_PIN_E; delay_us(1); POUT_LCD &= ~POUT_PIN_E; delay_us(160); Flex_port(0X03); POUT_LCD |= POUT_PIN_E; delay_us(1); POUT_LCD &= ~POUT_PIN_E; delay_us(160); Flex_port(NIBLE); POUT_LCD |= POUT_PIN_E; delay_us(1); POUT_LCD &= ~POUT_PIN_E; delay_us(160); Comando_LCD(0x28); Comando_LCD(0x08); Comando_LCD(0x01); // Comando_LCD(LINES_5X7 & FOUR_BIT); // Comando_LCD(DON & CURSOR_OFF & BLINK_OFF); // Comando_LCD(CLEAR); Comando_LCD(0x06); /* Entry Mode Set */ /* Incremento del cursor */ Comando_LCD(0x0C); return; } //********************************************************** /* Indica al LCD comandos */ //********************************************************** void Comando_LCD(unsigned char dato) { volatile unsigned char temp; /* variable auxiliar */ //delay_ms(10); /* Retardo de 10 mseg. */ POUT_LCD &=~POUT_PIN_RS; temp = dato; /* Respaldo del dato original */ dato = dato >> 4; /* Corrimiento del nible alto */ Flex_port(dato); POUT_LCD |= POUT_PIN_E; delay_us(1); POUT_LCD &=~POUT_PIN_E; Flex_port(temp); POUT_LCD |= POUT_PIN_E; delay_us(1); POUT_LCD &=~POUT_PIN_E; delay_us(2000); return; } //********************************************************** /* Manda datos al LCD */ //********************************************************** void Dato_LCD(unsigned char dato) { volatile unsigned char temp; /* variable auxiliar */ POUT_LCD |= POUT_PIN_RS; // delay_ms(10); /* Retardo de 10 mseg. */ temp = dato; /* Respaldo del dato original */ dato = dato >> 4; /* Corrimiento del nible alto */ Flex_port(dato); POUT_LCD |= POUT_PIN_E; delay_us(1); POUT_LCD &=~POUT_PIN_E; Flex_port(temp); delay_us(50); POUT_LCD |= POUT_PIN_E; delay_us(1); POUT_LCD &=~POUT_PIN_E; POUT_LCD &=~ POUT_PIN_RS; delay_us(50); return; } //********************************************************** // Escribe una cadena desde memoria de programa al LCD //********************************************************** void Datos_LCD(const char *buffer) { while(*buffer) // Write data to LCD up to null { Dato_LCD(*buffer); // Write character to LCD buffer++; // Increment buffer } return; } //********************************************************** // Escribe una cadena desde memoria de datos al LCD //********************************************************** void Dato_String_LCD(char *buffer) { while(*buffer) // Write data to LCD up to null { Dato_LCD(*buffer); // Write character to LCD buffer++; // Increment buffer } return; } void Flex_port(unsigned char data){ POUT_LCD &= ~BIT1_LCD; POUT_LCD &= ~BIT2_LCD; POUT_LCD &= ~BIT3_LCD; POUT_LCD &= ~BIT4_LCD; if(data & BIT0)POUT_LCD |= BIT1_LCD; if(data & BIT1)POUT_LCD |= BIT2_LCD; if(data & BIT2)POUT_LCD |= BIT3_LCD; if(data & BIT3)POUT_LCD |= BIT4_LCD; return; } void Dato_String_LCDEx(unsigned char xLine, char *buffer) { Comando_LCD(xLine); while(*buffer) // Write data to LCD up to null { Dato_LCD(*buffer); // Write character to LCD buffer++; // Increment buffer } return; } void Dato_LCDEx(unsigned char xLine, const char *buffer) { Comando_LCD(xLine); while(*buffer) // Write data to LCD up to null { Dato_LCD(*buffer); // Write character to LCD buffer++; // Increment buffer } return; } void GoToXY(unsigned char Line, unsigned char Position) { switch(Line) { case 1: Position += 128; Comando_LCD(Position); break; case 2: Position +=167; Comando_LCD(Position); break; } return; } void clear_LCD(void){ Dato_String_LCDEx(LN1," "); Dato_String_LCDEx(LN2," "); GoToXY(1,0); return; } void delay_us(unsigned int time){ while(--time)__delay_cycles (1); return; } void delay_ms(unsigned int time){ while(--time)__delay_cycles (1000); return; }
     

    #ifndef LCD_V1_H_ #define LCD_V1_H_ #include /* * File: LCD_v1.h * Author: THE CHILANGO POWER * * Created on 13 de julio de 2012, 03:32 PM */ // Manejo de un Display de Cristal Liquido LCD 16X4 // de 16 caracteres por 4 lineas, con una interface // de 4 lineas: // // Conexiones del LCD al Microcontrolador #define POUT_LCD P1OUT #define PDIR_LCD P1DIR #define POUT_PIN_RS BIT0 // Define la Columna 1 #define POUT_PIN_E BIT1 // Define la Columna 3 #define PDIR_PIN_RS BIT0 // Define la Columna 1 #define PDIR_PIN_E BIT1 // Define la Columna 3 #define BIT1_LCD BIT4 #define BIT2_LCD BIT5 #define BIT3_LCD BIT6 #define BIT4_LCD BIT7 #define PDIR_BIT1_LCD BIT4 #define PDIR_BIT2_LCD BIT5 #define PDIR_BIT3_LCD BIT6 #define PDIR_BIT4_LCD BIT7 /* Configuracion del Display y cursor */ #define DON 0X0F //0b00001111 /* Display encendido */ #define DOFF 0X0B //0b00001011 /* Display apagado */ #define CURSOR_HOME 0X02 //0b00000010 /* Cursor encendido */ #define CURSOR_ON 0X0F //0b00001111 /* Cursor encendido */ #define CURSOR_OFF 0X0C //0b00001100 /* Cursor apagado */ #define BLINK_ON 0X0F //0b00001111 /* Cursor con parpadeo */ #define BLINK_OFF 0X0E //0b00001110 /* Cursor sin parpadeo */ #define CLEAR 0X01 //0b00000001 /* Display encendido */ /* Modo de entrada */ #define INCREMENT 0X06 //0b00000110 /* Incrementa la posicion del cursor */ #define DECREMENT 0X04 //0b00000100 /* Decrementa la posicion del cursor */ /* Configuracion de los desplazamientos del cursor y del Display*/ #define SHIFT_CUR_LEFT 0X13 //0b00010011 /* Corrimiento del cursor a la izquierda */ #define SHIFT_CUR_RIGHT 0X17 //0b00010111 /* Corrimiento del cursor a la derecha */ #define SHIFT_DISP_LEFT 0X1B //0b00011011 /* Corrimiento del display a la izquierda */ #define SHIFT_DISP_RIGHT 0X1F //0b00011111 /* Corrimiento del display a la derecha */ /* Funciones de inicializacion */ #define NIBLE 0X02 //0b00000010 /* interface a 4 bits */ #define FOUR_BIT 0X2F //0b00101111 /* Interface a 4-bit */ #define EIGHT_BIT 0X3F //0b00111111 /* Interface a 8-bit */ #define LINE_5X7 0X33 //0b00110011 /* Una linea, caracter 5x7 */ #define LINE_5X10 0X37 //0b00110111 /* Una linea, caracter 5x10 */ #define LINES_5X7 0X3B //0b00111011 /* Dos lineas. character 5x7 */ /* Lineas de trabajo */ #define DDRAM_LINEA_1 0X80 //0b10000000 /* Linea 1 */ #define DDRAM_LINEA_2 0XC0 //0b11000000 /* Linea 2 */ #define DDRAM_LINEA_3 0X90 //0b10010000 /* Linea 3 */ #define DDRAM_LINEA_4 0XD0 //0b11010000 /* Linea 4 */ #define LN1 DDRAM_LINEA_1 #define LN2 DDRAM_LINEA_2 /// Configuracion del puerto // /////////////////////////////////////////////////////////////////////////////// //Prototipos de funciones /////////////////////////////////////////////////////////////////////////////// void Flex_port(unsigned char data); void Inicializa_LCD(void); /* Inicializa LCD */ void Comando_LCD(unsigned char dato); /* Indica al LCD un comando */ void Dato_LCD(unsigned char dato); /* Indica al LCD un caracter */ void Datos_LCD(const char *buffer); /* escribe una cadena desde la memoria de programa al LCD */ void Dato_String_LCD(char *buffer); /* escribe una cadena desde la memoria de datos al LCD */ void Dato_String_LCDEx(unsigned char xLine, char *buffer); void Dato_LCDEx(unsigned char xLine, const char *buffer); void GoToXY(unsigned char Line, unsigned char Position); void delay_us(unsigned int time); void clear_LCD(void); void delay_ms(unsigned int time); #endif /* LCD_V1_H_ */
  4. Like
    jsolarski reacted to yyrkoon in MAX31855 based reflow oven controller   
    First, Much thanks to Rickta59 for helping me understand various aspects of the MSP430 in hardware, and software. Then to Spirilis who wrote the SPI initialization, and usage code in an attempt to help me understand HW SPI better. It worked Also to the many others who have helped me on these forums. 
     
    I need to mention this project is still in design phase. PCB layout is nearing final stages. Layout / schematics design is done in OrCAD, and as I've been informed most ( or all ? ) everyone here uses EagleCAD. Sorry, but nothing I can do about that, and have been unsuccessful, in finding any reasonably priced conversion tools. In the end the layout software used is not up to me. 
     
    I do not know how many would be interested in a PCB, but the board will be usable as a stand alone board, or as a boosterpack. Everything as I understand it part wise should be thru-hole, for easy hand soldering.  But depending on how many people would like one, price per would be around $5 each, plus shipping from us to you. USPS should be around $2 - $3, US only. Anyway, not looking to make anything here, just looking to lower costs per person( including ourselves ). 
     
    below is a PDF attachment of the schematic for those who wish to view it.
     
    EDIT:
     
    Also I am ( and have been ) writing the software "library" for this board as we speak. The idea is to use an LCD, a couple of buttons for menu selection, then optional fan, and buzzer. So far I have a table driven "state machine" implemented in code, with initialization for UART ( debugging using printf(), but can leave this in too ), Minimal SPI communications, and have the code reading values out of the MAX31855, and displaying them out over UART -> serial printing various information. Again, the UART -> serial functionality is meant for debugging, but could be left in as the code will likely never even reach 8kb in total.
     
    Anyways questions are welcome, if there are any to be had.
     
    EDIT:
     
    reflow.zip uploaded for use with these reflow oven boards.
    SCHEMATIC1 _ PAGE1.pdf
    reflow.zip
  5. Like
    jsolarski reacted to antennahead in Bare Bones F5172 EVM   
    This board is now available from Schmartboard:
     
    http://www.schmartboard.com/index.asp?page=products_dev&id=641
     
     
  6. Like
    jsolarski reacted to antennahead in Bare Bones F5172 EVM   
    I've also created a 'F5172 eval board, but a simpler design.  See attached image.
     
    This design was motivated by a need at U. of Colorado, Boulder for a Timer_D enabled '430 for use in their senior level power lab class.
     
    Class starts on Monday, 1/14/2013.
     
    Schematic and BOM is attached.
     
    This board will be available for purchase from Schmartboard (http://www.schmartboard.com/) probably in about a month.
     
    Model #710-0009-01, board size is 2"x3" with 0.1" headers and the usual MSP430 UIF interface.
     
    It will cost between $20-$30 depending on if you want the MSP stuffed or not.
     
    If there is enough interest, I can spin the gerbers and delete Schmartboard's proprietary board outline and logo if people want to roll their own.
     
    Best regards,
    S. Dunbar
    Texas Instruments, FAE
     
     
    schematic.pdf
    BOM.pdf

  7. Like
    jsolarski reacted to RobG in Interesting RFID board   
    Got the boards, they are very cool.
    I wish TI had a TRF79xx board in this price range.
    Hey, how about BP? Just in time for the BP Design Challenge
     
     

  8. Like
    jsolarski reacted to igendel in Tilt-sensitive rolling ball display   
    Hi all,
     
    Just to show off a little something I did It's an LCD display of a "ball" rolling around on a spotted surface, and bouncing from the boundries. The direction and speed of rolling is determined by the tilt of the entire setup. 
     
    The hardware is a Nokia 5110 LCD breakout and a cheap 3-axis accelerometer breakout, both hooked directly to the MSP430 Launchpad. Code was written in Energia. 
     
    Here's the video:

     
    I don't consider the code clean enough to publish, however I'll be happy to answer any questions about it.
     
    Happy coding!
  9. Like
    jsolarski reacted to bluehash in Elecrow PCB Service - Free color   
    I have a batch of 100 PCBs for the store from them. Will update when they arrive.
  10. Like
    jsolarski got a reaction from rebeltaz in any reason not to place capacitor between P1.x and gnd?   
    It has the same effect as putting a cap near the power pins, to clean up the noise, I think in theory is should work like its supposed to.
     
    I really cant think of any reason not to, I would do the same thing for noise on a pin or input.
  11. Like
    jsolarski reacted to mbeals in Project deathbot   
    The chassis came in today so I built it with the dual gearbox and mocked it up with both my launchpad and my STM32F3.  There is enough room between the plates that I should be able to house the batteries and all related electronics down there, leaving the top plate completely open for sensors and control electronics.
     
    I also got the ultrasonic sensor and hooked it up well enough to get some signal on my scope, so now I just need to start working on interfacing it with the other electronics.



  12. Like
    jsolarski reacted to grodius in Help! MMA8452Q accelerometer with Launchpad   
    1) if the accelerometer is on a breakout then you can commit to that device and get started.  If it's just a 20 pin QFN probably I recommend something on a breakout board while you experiment.
     
    2) I recommend CDE's I2C explorer found on this forum as a starting point.  Get that going on your microcontroller and serial terminal.  It would help to find out whether you will be using a 2452 or earlier 2231.
     
    I disabled all internal pullups within the code and made a UART change for it to work with the 2452.
     
    In general you will only need 4 wires to connect a device:
     
    - most 3.3 LDO voltage regulators provided on the cheap breakout boards seem to be happy with the 3.6v the launchpad provides
    - ground
    - SDA and SCL ( I pull these high with 4K7 ohm) SDA 1.7 SCL 1.6
     
    other broken out lines are generally used for addressing/chip select (which I do do) or slave initiated interrupts which will likely be of high interest in your freefall detection.
     
    In general, many devices will have:
     
    - a sleep/wake register you will write to to begin taking readings
    - a series of data registers you can read at your master initiated leisure
     
    - you will want to find the register/s to set a freefall interrupt on a pin if that suits.
     
    Often there is so much confusion on the internet that the datasheet is the simplest first place to look, but being lazy I usually look for an arduino sample and look for:
     
    - slave address
    - initiation register and value ( usually to wake from sleep mode )
    - data register
     
    (*devices will vary but accelerometers seem pretty similar for that at least)
     
    I will then use the I2C explorer with the search 's' command to confirm it is communicating.  It will display the 2 cooked slave addresses. Familiarize yourself with the I2C Slave address shifting semantics for R and W. [ SLAVE ADDRESS 7 bits (left shifted 1 bit)  ][ W:0 R:1 1 bit ].  Different modules and/or software will address this single byte differently.
     
    After that I would study the datasheet and find out range setting / power modes etc and, in the case of the Invensense MPU6050, lament why oh why such power must be deliberately obfuscated and withheld from the hobbyist community.   I should be preaching read the datasheet thoroughly first, but in reality once your I2C is up and running it is simple enough that you go straight to raw data reading and then backwards to modes etc from there.
  13. Like
    jsolarski reacted to RobG in 4x4 RGB Matrix Booster Pack with WS2812 / WS2812B LEDs   
    Created as part of GB#11, this booster pack uses 5050 RGB LEDs with integrated WS2811.
    Will post code examples later on.
     

     
    BTW, I cannot get a preview of this YouTube video to show up, can you check it out B#?
     
     
     

  14. Like
    jsolarski reacted to RobG in RGB Globe   
    Boards are assembled, now on to the base and the controller.

     
    Here's the short assembly video
     

     
     
    And here's the schematic of a single section

  15. Like
    jsolarski reacted to cubeberg in What are you working on today/this week?   
    I'm working on my Sewable project

     
    Hoping to finish wiring the rest of the LEDs and get the first one finished
  16. Like
    jsolarski reacted to GyrocopterLLC in LiPoly Battery Management   
    Here's a little something I've been tinkering with for some time now. My goal (obsession?) for a couple years has been to build an electric bike using hardware and software that I develop myself. This is unquestionably a bad idea - there are plenty of commercially available motor controllers, chargers, displays, et cetera that I could use. My drive to build it myself, however, prevents me from buying when I could instead build. Whatever, I've already gone on too long. HERE'S THE PROJECT ALREADY:
     
    When using series connected batteries it's important to ensure that all the batteries are at a similar state of charge. If one battery in a line gets depleted before the rest, you're gonna have a bad day. It will continue to drop in voltage and risk being dangerously under charged while the other batteries remain healthy. Similar badness can occur while charging the pack. Therefore, one should use some sort of monitoring and balancing device. This is especially important in lithium batteries, which can be rather fickle when it comes to charge levels. Lead acid can often take more of a beating, but lithium REALLY REALLY don't like being under- or over-charged.
     

     
    The four red boards are my battery management system (BMS). They read off the individual cell levels of those 4 blue bricks, the lithium polymer battery packs. Each brick contains 4 series-connected batteries, usually charged anywhere between 3.5 to 4.2 volts (so each brick is about 14 to 16.8V, depending on state of charge). The clump of wiring is a daisy-chained, optically-isolated serial port connection. The master will address each BMS slave board sequentially down the line. If a board receives a message that has a different address, it passes it on down the line. If it's a message for that board, it responds back up.
     
    Additionally, the boards have 4 shunt resistors, one for each cell. While charging, if a cell reaches 4.2V (fully charged) the shunt turns on, slowly draining charge so the other cells can catch up.
     
    This is what OshPark thinks the boards look like:
     

     
    The series-connected batteries supply the MSP430G2553 power through an AP1117 LDO regulator. Each cell is measured with voltage divider resistors. There's an option for an analog switch chip if I wanted to REALLY REALLY bring down standby current (turning off the voltage dividers). The serial port is kinda funky...the upstream Tx connection goes into P1.1 (USCI Rx), and Rx connection into P1.2 (USCI Tx). The downstream Tx connection is sent from P3.7 (software UART). The downstream Rx is paralleled with the upstream Tx. So that means all boards talk on the same wires (the opto-coupler open-collector outputs are connected together). But incoming data goes to one board at a time. Messages coming in from a master will travel down the chain until they reach the addressed board, and responses will go back up the chain immediately.
     
    This is my first (non-"Hi from new users") post, so please please please tell me if I did anything wrong, or if anybody wants some more information. I have schematics/layout (KiCad) and code (CCS), too. The project isn't quite done yet. I'm tinkering with the ADC calibrations, some more serial port commands, and I haven't even soldered the shunt resistors on yet.
     
    {Minutes later edit} I forgot to mention WHY I did that stuff with optocouplers. The ground for each board is referenced to its battery pack. Since I'm going to be connecting the packs in series, that means if I were to share ground between boards I would be shorting at least one of the 16-something volt LiPoly batteries to its ground. 
  17. Like
    jsolarski reacted to GeekDoc in Watch Dog Timer   
    Don't forget the option of re-purposing it for use as another timer!
  18. Like
    jsolarski reacted to SugarAddict in Tis the season for divinity   
    I can make this recipe all year round... I use corn syrup from restaurant supply shops, it's a LOT thicker than that stuff you get in the grocery store.. and it comes in 5 gallon buckets (43 DE).
     
    plenty of wax paper on the counter top near the mixing area
    3 1/2 cups sugar
    2/3 cup water
    2/3 cup corn syrup
    2 or 3 egg whites (I tend to do this one by experience... If you use eggs much you'll notice some have more egg white than others. If you get a lot of egg white out of 2 eggs, that's "ok", if you get some but not a lot... use 3, if you're not sure, use 3.)
    touch of salt (I do two twists on the salt grinder with a very fine setting)
     
    Bring corn syrup, water, and sugar to a boil, 250
  19. Like
    jsolarski reacted to abecedarian in Tis the season for divinity   
    I think I may indulge my sadistic side and give my wife this, and tell her she has to use chop sticks to stiffen the egg whites and blend the syrup mixture in.
  20. Like
    jsolarski reacted to spirilis in Watch Dog Timer   
    You have the basic idea correct, in addition with the WDTTMSEL bit (in WDTCTL) set on you can use it as an "interval" timer where it'll generate an interrupt every so often... A common use of the WDT, in my personal experience anyway.  That way the other timer modules are free to do other things (like PWM).  I often use this as a scheduler to periodically wake-up the chip for performing a task or checking something, then I have the chip go back to sleep until the next interval elapses.
     
    By default, on power-up, the Watchdog is enabled (and in Watchdog mode; after 32768 cycles of the SMCLK it'll reset the chip).  You absolutely have to disable the WDT as the very first thing (or at least one of the first things) in your main() function.
     
    WDTCTL = WDTPW | WDTHOLD;
     
    is the typical way to do so.
     
    If you actually do intend to use the WDT module as a watchdog (to reset the chip if it goes unresponsive, i.e. for critical uses where you need reliability against potential code bugs), you'll also want to read (and clear) the WDTIFG bit from the IFG1 register shortly after to determine if your chip reset because of a watchdog timeout.
  21. Like
    jsolarski got a reaction from pimmel in Makefile for MSPGCC   
    here are the 2 make files I use for mspgcc - for use or comparison
     

    OBJECTS = main.o CC = msp430-gcc CFLAGS =-Os -Wall -g -mmcu=msp430x2011 all : $(OBJECTS) $(CC) $(CFLAGS) $(OBJECTS) -o main.elf %.o : %.c $(CC) $(CFLAGS) -c $< clean: rm -fr $(OBJECTS) main.elf erase: mspdebug rf2500 "erase" upload: mspdebug rf2500 "prog main.elf" size: msp430-size main.elf
     

    CC=msp430-gcc CFLAGS=-Os -Wall -g -mmcu=msp430g2231 OBJS=main.c all: $(OBJS) $(CC) $(CFLAGS) -o main.elf $(OBJS) %.o: %.c $(CC) $(CFLAGS) -c $< clean: rm -fr main.elf $(OBJS)
     
     
    very simple and no extra flags
     
    as for all your flags, time to get out the gcc manual lol
  22. Like
    jsolarski reacted to oPossum in How to use temperature calibration data   
    [tipdf]SLAU144[/tipdf] chapter 24 describes the calibration data stored as TLV (tag length value) in info segment A. There are ADC values for 30C and 85C for both 1.5V and 2.5V internal reference voltages. These temperature calibration values can be used to improve the accuracy of the internal temperature sensor. There is no explanation of how to do this, so here is how to do it...
     
    Before using calibration data it would be a good idea to validate the info segment checksum. The checksum is stored in the first word and is the negative of the XOR of all of the following words. This function will return 0 for a valid checksum.

    unsigned verify_info_chk(const unsigned * const begin, const unsigned * const end) { const unsigned *p = begin + 1; // Begin at word after checksum unsigned chk = 0; // Init checksum while(p < end) chk ^= *p++; // XOR all words in segment return chk + *begin; // Add checksum - result will be zero if checksum is valid }
     
    Each chunk of calibration data in the info segment has a unique tag. This function will search for a specified tag and return a pointer to it. It will return NULL if the tag is not found.

    void const *find_tag(const unsigned * const begin, const unsigned * const end, const unsigned tag) { const unsigned *p = begin + 1; // Begin at word after checksum do { // const unsigned d = *p++; // Get a word if((d & 0xFF) == tag) return (void *)p; // Return pointer if tag matches p += (d >> 9); // Point to next tag } while(p < end); // While still within segment return 0; // Not found, return NULL pointer }
     
    A structure would be handy for using the ADC/temperature cal data...

    typedef struct { unsigned adc_gain; // ADC gain unsigned adc_offet; // ADC offset unsigned ref15; // ADC value of 1.5 volt input when using 1.5 volt reference unsigned t3015; // ADC value of 30C when using 1.5 volt reference unsigned t8515; // ADC value of 85C when using 1.5 volt reference unsigned ref25; // ADC value of 2.5 volt input when using 2.5 volt reference unsigned t3025; // ADC value of 30C when using 2.5 volt reference unsigned t8525; // ADC value of 85C when using 2.5 volt reference } TCAL;
     
    Find tag 0x08 and setup a pointer to the struct...

    const TCAL * const cal = (TCAL *)find_tag(info_seg_a, info_seg_a_end, 0x08);
     
    Now the scale and offset values for the temperature conversion formulas can be calculated...

    const long cc_scale = ((85L - 30) << 16) / (cal->t8515 - cal->t3015); const long cc_offset = -(cal->t3015 * cc_scale) + (30L << 16) + (1 << 15); const long ck_offset = cc_offset + (273.15 * (1L << 16)); const long cf_scale = ((185L - 86) << 16) / (cal->t8515 - cal->t3015); const long cf_offset = -(cal->t3015 * cf_scale) + (86L << 16) + (1 << 15);
     
    Those formulas show the derivation, they can be simplified and combined with basic error handling. The scale and offset values will be zero if the checksum is invalid or the calibration data is not found.

    const TCAL * const cal = (TCAL *)(verify_info_chk(info_seg_a, info_seg_a_end) \ ? 0 \ : find_tag(info_seg_a, info_seg_a_end, 0x08)); const long cc_scale = cal ? 3604480L / (cal->t8515 - cal->t3015) : 0; const long cf_scale = cal ? 6488064L / (cal->t8515 - cal->t3015) : 0; const long cc_offset = cal ? 1998848L - (cal->t3015 * cc_scale) : 0; const long cf_offset = cal ? 5668864L - (cal->t3015 * cf_scale) : 0; const long ck_offset = cc_offset + 17901158L;
     
    In some cases you may want to default to the uncalibrated values...

    const TCAL * const cal = (TCAL *)(verify_info_chk(info_seg_a, info_seg_a_end) \ ? 0 \ : find_tag(info_seg_a, info_seg_a_end, 0x08)); const long cc_scale = cal ? 3604480L / (cal->t8515 - cal->t3015) : 27069L; const long cf_scale = cal ? 6488064L / (cal->t8515 - cal->t3015) : 48724L; const long cc_offset = cal ? 1998848L - (cal->t3015 * cc_scale) : -18169625L; const long cf_offset = cal ? 5668864L - (cal->t3015 * cf_scale) : -30634388L; const long ck_offset = cc_offset + 17901158L;
     
     
    Now the actual scaled temperature values can be calculated with the usual scale/offset formulas...

    dcc = ((cc_scale * adc) + cc_offset) >> 16; // C calibrated dkc = ((cc_scale * adc) + ck_offset) >> 16; // K calibrated dfc = ((cf_scale * adc) + cf_offset) >> 16; // F calibrated
     
    Code for Nokia 7110 that will show uncalibrated (left) and calibrated (right) temperature in F, C, and K.
     

     
    main.cpp

    #include #include #include "nokia7110tl.h" using namespace nokia7110; /* P1.0 Reset P1.3 Temp Sensor (Not used) P2.0 Serial Data P2.1 Backlight P2.2 Chip Select P2.3 Data/Command P2.4 Serial Clock P2.5 Button */ // P1 static const unsigned LCD_RESET = BIT0; static const unsigned RXD = BIT2; static const unsigned SWITCH = BIT3; // P2 static const unsigned LCD_DATA = BIT0; static const unsigned LCD_BACKLIGHT = BIT1; static const unsigned LCD_CE = BIT2; static const unsigned LCD_DC = BIT3; static const unsigned LCD_CLK = BIT4; static const unsigned LCD_BTN = BIT5; Nokia7110 lcd; // Print integer from -999 to 9999 using 12 x 16 font void print_int(int i, unsigned x, const unsigned y) { if(i < -999 || i > 9999) return; const unsigned e = x; x += 48; const unsigned neg = i < 0; if(neg) i = -i; div_t d; d.quot = i; do { d = div(d.quot, 10); lcd.pd12(d.rem, x -= 12, y); } while(d.quot); if(neg) lcd.pd12(14, x -= 12, y); while(x > e) lcd.pd12(10, x -= 12, y); } // Print integer from -999 to 9999 using 6 x 8 font void print_int_small(int i, unsigned x, const unsigned y) { if(i < -999 || i > 9999) return; const unsigned e = x; x += 24; const unsigned neg = i < 0; if(neg) i = -i; div_t d; d.quot = i; do { d = div(d.quot, 10); lcd.print(x -= 6, y, '0' + d.rem); } while(d.quot); if(neg) lcd.print(x -= 6, y, '-'); while(x > e) lcd.print(x -= 6, y, ' '); } #pragma vector = ADC10_VECTOR // ADC conversion complete interrupt __interrupt void ADC10_ISR(void) // { // __bic_SR_register_on_exit(LPM0_bits); // Wakeup main code } // unsigned verify_info_chk(const unsigned * const begin, const unsigned * const end) { const unsigned *p = begin + 1; // Begin at word after checksum unsigned chk = 0; // Init checksum while(p < end) chk ^= *p++; // XOR all words in segment return chk + *begin; // Add checksum - result will be zero if checksum is valid } void const *find_tag(const unsigned * const begin, const unsigned * const end, const unsigned tag) { const unsigned *p = begin + 1; // Begin at word after checksum do { // const unsigned d = *p++; // Get a word if((d & 0xFF) == tag) return (void *)p; // Return pointer if tag matches p += (d >> 9); // Point to next tag } while(p < end); // While still within segment return 0; // Not found, return NULL pointer } typedef struct { unsigned adc_gain; // ADC gain unsigned adc_offet; // ADC offset unsigned ref15; // ADC value of 1.5 volt input when using 1.5 volt reference unsigned t3015; // ADC value of 30C when using 1.5 volt reference unsigned t8515; // ADC value of 85C when using 1.5 volt reference unsigned ref25; // ADC value of 2.5 volt input when using 2.5 volt reference unsigned t3025; // ADC value of 30C when using 2.5 volt reference unsigned t8525; // ADC value of 85C when using 2.5 volt reference } TCAL; int main(void) { unsigned adc; int dc, dk, df; // Temperature in degrees C, K, and F int dcc, dkc, dfc; // Calibrated temperatures const unsigned * const info_seg_a = (unsigned *)0x10C0; // Address of info segement A const unsigned * const info_seg_a_end = info_seg_a + 32; // 32 words in each segment WDTCTL = WDTPW | WDTHOLD; P1REN = RXD | SWITCH; P1DIR = LCD_RESET; P1OUT = RXD | SWITCH | LCD_RESET; P2DIR = LCD_DC | LCD_CE | LCD_CLK | LCD_BACKLIGHT | LCD_DATA; P2REN = LCD_BTN; P2OUT = LCD_CLK | LCD_DC | LCD_CE | LCD_BACKLIGHT | LCD_BTN; ADC10CTL0 = 0; // Configure ADC ADC10CTL1 = INCH_10 | ADC10DIV_3; // ADC10CTL0 = SREF_1 | ADC10SHT_3 | REFON | ADC10ON | ADC10IE; ADC10CTL0 |= ADC10IE; // Enable ADC conversion complete interrupt // _EINT(); // Enable interrupts // const TCAL * const cal = (TCAL *)(verify_info_chk(info_seg_a, info_seg_a_end) \ ? 0 \ : find_tag(info_seg_a, info_seg_a_end, 0x08)); const long cc_scale = cal ? 3604480L / (cal->t8515 - cal->t3015) : 0; const long cf_scale = cal ? 6488064L / (cal->t8515 - cal->t3015) : 0; const long cc_offset = cal ? 1998848L - (cal->t3015 * cc_scale) : 0; const long cf_offset = cal ? 5668864L - (cal->t3015 * cf_scale) : 0; const long ck_offset = cc_offset + 17901158L; lcd.reset(); // lcd.init(); // // lcd.clear(); // // for(; { // for-ever ADC10CTL0 |= (ENC | ADC10SC); // Begin ADC conversion __bis_SR_register(LPM0_bits + GIE); // Sleep until conversion complete adc = ADC10MEM; // Read ADC // // Convert to temperature dc = ((27069L * adc) - 18169625L) >> 16; // C dk = ((27069L * adc) - 268467L) >> 16; // K df = ((48724L * adc) - 30634388L) >> 16; // F // dcc = ((cc_scale * adc) + cc_offset) >> 16; // C calibrated dkc = ((cc_scale * adc) + ck_offset) >> 16; // K calibrated dfc = ((cf_scale * adc) + cf_offset) >> 16; // F calibrated // // Display on LCD print_int(df, 0, 0); // Degrees F print_int(dfc, 48, 0); // Degrees F calibrated print_int(dc, 0, 3); // Degrees C print_int(dcc, 48, 3); // Degrees C calibrated print_int(dk, 0, 6); // Degrees K print_int(dkc, 48, 6); // Degrees K calibrated } // return 0; }
     
    nokia7110tl.h

    namespace nokia7110 { unsigned char PNONE; typedef enum { lcd_command = 0, // Array of one or more commands lcd_data = 1, // Array of one or more bytes of data lcd_data_repeat = 2 // One byte of data repeated } lcd_cmd_type; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> struct Nokia7110 { void write(const unsigned char *cmd, unsigned len, const lcd_cmd_type type = lcd_data); void reset(void); void init(void); void home(void); void pos(unsigned char x, unsigned char y); void clear(unsigned char x = 0); void fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z); void bitmap(const unsigned char *bmp, signed char x, signed char y, unsigned char w, unsigned char h); inline void bitmap(const unsigned char *bmp, signed char x, signed char y) { bitmap(bmp + 2, x, y, bmp[0], bmp[1]); }; void print(char c); inline void print(unsigned char x, unsigned char y, char c) { pos(x, y); print(c); }; void print(const char *s); inline void print(unsigned char x, unsigned char y, const char *s) { pos(x, y); print(s); }; void print(const char *s, unsigned char m); void printv(unsigned char x, unsigned char y, char *s); void pd12(unsigned n, unsigned x, unsigned y); }; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::write(const unsigned char *cmd, unsigned len, const lcd_cmd_type type) { register unsigned mask; if(&_EP != &PNONE) _EP &= ~_CE; do { mask = 0x0080; do { if(*cmd & mask) { _SP |= _DATA; _SP &= ~_CLK; } else { _SP &= ~(_CLK | _DATA); } _SP |= _CLK; mask >>= 1; } while(!(mask & 1)); if(!type) { if(&_CP == &PNONE) { __delay_cycles(_DC); } else { _CP &= ~_DC; } } if(*cmd & mask) { _SP |= _DATA; _SP &= ~_CLK; } else { _SP &= ~(_CLK | _DATA); } _SP |= _CLK; if(&_CP != &PNONE) _CP |= _DC; if(!(type & 2)) ++cmd; } while(--len); if(&_EP != &PNONE) _EP |= _CE; } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::reset(void) { if(&_RP == &PNONE) { // --- Set initial state of CLK, DC and CE as needed // * = output used for reset if(&_CP == &PNONE) { if(&_EP != &PNONE) { // CLK*, DATA, CE _EP |= _CE; } // else // CLK*, DATA } else { if(&_EP != &PNONE) { // CLK, DATA, DC*, CE if(&_SP == &_EP) { _SP |= (_CLK | _CE); } else { _SP |= _CLK; _EP |= _CE; } } else { // CLK, DATA, DC* _SP |= _CLK; } } // --- Reset pulse on CLK or DC as needed if(&_CP == &PNONE) { // No DC port, use CLK to reset _SP &= ~_CLK; __delay_cycles(_RD); _SP |= _CLK; } else { // Use DC to reset _CP &= ~_DC; __delay_cycles(_RD); _CP |= _DC; } } else { _RP &= ~_RST; if(&_EP != &PNONE) { if(&_SP == &_EP) { _SP |= (_CLK | _CE); } else { _SP |= _CLK; _EP |= _CE; } } else { _SP |= _CLK; } __delay_cycles(_RD); _RP |= _RST; } __delay_cycles(_RD); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::init(void) { /* static const unsigned char init[] = { 0x20 | 0x01, // Function set - extended instructions enabled //0x80 | 64, // Set vop (contrast) 0 - 127 0x80 | 70, // Higher contrast improves animation 0x04 | 2, // Temperature control 0x10 | 3, // Set bias system 0x20 | 0x00, // Function set - chip active, horizontal addressing, basic instructions 0x08 | 0x04 // Display control - normal mode }; */ static const unsigned char init[] = { 0xA6, //Display: Normal 0xA3, //LCD Bias Settings: 1/7 0xA1, //ADC Selection: Reverse 0xC0, //Common Output: Normal Direction //0xC8, //Common Output: Upside Down 0x22, //Set the V5 output Voltage 0x81, //Set Electronic Volume Register 0x2E, //Power Controller Set // Booster circuit: ON // Voltage regulator circuit: ON // Voltage follower circuit: OFF 0x2F, //Power Controller Set // Voltage follower circuit: ON 0xE3, //Non-OPeration Command 0x40, //Set the start line 0xAF, //LCD On //0xA5, //Display All Points: ON 0xA4, //Display All Points: NORMAL }; write(init, sizeof(init), lcd_command); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::home(void) { //static const unsigned char home[] = { 0x40, 0x80 }; static const unsigned char home[] = { 0xB0, 0x11, 0x02 }; write(home, sizeof(home), lcd_command); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::pos(unsigned char x, unsigned char y) { unsigned char c[3]; /*c[0] = 0x80 | x; c[1] = 0x40 | y;*/ x += 18; c[0] = 0xB0 | y; c[1] = 0x10 | (x >> 4); c[2] = x & 0x0F; write(c, sizeof(c), lcd_command); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::clear(unsigned char x) { #if 0 home(); write(&x, 504, lcd_data_repeat); home(); #else for(unsigned y = 0; y < 9; ++y) { pos(0, y); write(&x, 96, lcd_data_repeat); } #endif } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z) { #if 0 unsigned yy = y + h; unsigned char c[2]; c[0] = 0x80 | x; for(;y < yy; ++y) { c[1] = 0x40 | y; write(c, sizeof(c), lcd_command); write(&z, w, lcd_data_repeat); } #else unsigned yy = y + h; unsigned char c[3]; x += 18; c[1] = 0x10 | (x >> 4); c[2] = (x & 0x0F); for(;y < yy; ++y) { c[0] = 0xB0 | y; write(c, sizeof(c), lcd_command); write(&z, w, lcd_data_repeat); } #endif } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::bitmap(const unsigned char *bmp, signed char x, signed char y, unsigned char w, unsigned char h) { unsigned char c[3]; unsigned char ww; if(x < 0) { ww = w + x; bmp -= x; x = 0; } else if(x + w >= 96) { ww = (96 - x); } else { ww = w; } /*c[0] = 0x80 | x; c[1] = 0x40 | y;*/ x += 18; c[0] = 0xB0 | y; c[1] = 0x10 | (x >> 4); c[2] = x & 0x0F; while(h--) { write(c, sizeof(c), lcd_command); write(bmp, ww); bmp += w; //++c[1]; ++c[0]; } } static const unsigned char font[96][5] = { 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00, 0x00, 0x5F, 0x00, 0x00, // ! 0x00, 0x07, 0x00, 0x07, 0x00, // " 0x14, 0x7F, 0x14, 0x7F, 0x14, // # 0x24, 0x2A, 0x7F, 0x2A, 0x12, // $ 0x23, 0x13, 0x08, 0x64, 0x62, // % 0x36, 0x49, 0x56, 0x20, 0x50, // & 0x00, 0x08, 0x07, 0x03, 0x00, // ' 0x00, 0x1C, 0x22, 0x41, 0x00, // ( 0x00, 0x41, 0x22, 0x1C, 0x00, // ) 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, // * 0x08, 0x08, 0x3E, 0x08, 0x08, // + 0x00, 0x40, 0x38, 0x18, 0x00, // , 0x08, 0x08, 0x08, 0x08, 0x08, // - 0x00, 0x00, 0x60, 0x60, 0x00, // . 0x20, 0x10, 0x08, 0x04, 0x02, // / 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0 0x00, 0x42, 0x7F, 0x40, 0x00, // 1 0x42, 0x61, 0x51, 0x49, 0x46, // 2 0x21, 0x41, 0x49, 0x4D, 0x33, // 3 0x18, 0x14, 0x12, 0x7F, 0x10, // 4 0x27, 0x45, 0x45, 0x45, 0x39, // 5 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6 0x41, 0x21, 0x11, 0x09, 0x07, // 7 0x36, 0x49, 0x49, 0x49, 0x36, // 8 0x06, 0x49, 0x49, 0x29, 0x1E, // 9 0x00, 0x00, 0x14, 0x00, 0x00, // : 0x00, 0x00, 0x40, 0x34, 0x00, // ; 0x00, 0x08, 0x14, 0x22, 0x41, // < 0x14, 0x14, 0x14, 0x14, 0x14, // = 0x00, 0x41, 0x22, 0x14, 0x08, // > 0x02, 0x01, 0x51, 0x09, 0x06, // ? 0x3E, 0x41, 0x5D, 0x59, 0x4E, // @ 0x7C, 0x12, 0x11, 0x12, 0x7C, // A 0x7F, 0x49, 0x49, 0x49, 0x36, // B 0x3E, 0x41, 0x41, 0x41, 0x22, // C 0x7F, 0x41, 0x41, 0x41, 0x3E, // D 0x7F, 0x49, 0x49, 0x49, 0x41, // E 0x7F, 0x09, 0x09, 0x09, 0x01, // F 0x3E, 0x41, 0x49, 0x49, 0x7A, // G 0x7F, 0x08, 0x08, 0x08, 0x7F, // H 0x00, 0x41, 0x7F, 0x41, 0x00, // I 0x20, 0x40, 0x41, 0x3F, 0x01, // J 0x7F, 0x08, 0x14, 0x22, 0x41, // K 0x7F, 0x40, 0x40, 0x40, 0x40, // L 0x7F, 0x02, 0x1C, 0x02, 0x7F, // M 0x7F, 0x04, 0x08, 0x10, 0x7F, // N 0x3E, 0x41, 0x41, 0x41, 0x3E, // O 0x7F, 0x09, 0x09, 0x09, 0x06, // P 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q 0x7F, 0x09, 0x19, 0x29, 0x46, // R 0x26, 0x49, 0x49, 0x49, 0x32, // S 0x01, 0x01, 0x7F, 0x01, 0x01, // T 0x3F, 0x40, 0x40, 0x40, 0x3F, // U 0x1F, 0x20, 0x40, 0x20, 0x1F, // V 0x3F, 0x40, 0x38, 0x40, 0x3F, // W 0x63, 0x14, 0x08, 0x14, 0x63, // X 0x03, 0x04, 0x78, 0x04, 0x03, // Y 0x61, 0x51, 0x49, 0x45, 0x43, // Z 0x00, 0x7F, 0x41, 0x41, 0x41, // [ 0x02, 0x04, 0x08, 0x10, 0x20, // '\' 0x00, 0x41, 0x41, 0x41, 0x7F, // ] 0x04, 0x02, 0x01, 0x02, 0x04, // ^ 0x80, 0x80, 0x80, 0x80, 0x80, // _ 0x00, 0x03, 0x07, 0x08, 0x00, // ' 0x20, 0x54, 0x54, 0x54, 0x78, // a 0x7F, 0x28, 0x44, 0x44, 0x38, // b 0x38, 0x44, 0x44, 0x44, 0x28, // c 0x38, 0x44, 0x44, 0x28, 0x7F, // d 0x38, 0x54, 0x54, 0x54, 0x18, // e 0x00, 0x08, 0x7E, 0x09, 0x02, // f 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g 0x7F, 0x08, 0x04, 0x04, 0x78, // h 0x00, 0x44, 0x7D, 0x40, 0x00, // i 0x00, 0x20, 0x40, 0x40, 0x3D, // j 0x00, 0x7F, 0x10, 0x28, 0x44, // k 0x00, 0x41, 0x7F, 0x40, 0x00, // l 0x7C, 0x04, 0x78, 0x04, 0x78, // m 0x7C, 0x08, 0x04, 0x04, 0x78, // n 0x38, 0x44, 0x44, 0x44, 0x38, // o 0xFC, 0x18, 0x24, 0x24, 0x18, // p 0x18, 0x24, 0x24, 0x18, 0xFC, // q 0x7C, 0x08, 0x04, 0x04, 0x08, // r 0x48, 0x54, 0x54, 0x54, 0x24, // s 0x04, 0x04, 0x3F, 0x44, 0x24, // t 0x3C, 0x40, 0x40, 0x20, 0x7C, // u 0x1C, 0x20, 0x40, 0x20, 0x1C, // v 0x3C, 0x40, 0x30, 0x40, 0x3C, // w 0x44, 0x28, 0x10, 0x28, 0x44, // x 0x4C, 0x90, 0x90, 0x90, 0x7C, // y 0x44, 0x64, 0x54, 0x4C, 0x44, // z 0x00, 0x08, 0x36, 0x41, 0x00, // { 0x00, 0x00, 0x77, 0x00, 0x00, // | 0x00, 0x41, 0x36, 0x08, 0x00, // } 0x02, 0x01, 0x02, 0x04, 0x02, // ~ 0x00, 0x06, 0x09, 0x09, 0x06, // degrees }; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::print(char c) { write(&font[c - 32][0], 5); write(&font[0][0], 1); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::print(const char *s) { while(*s) { write(&font[*s - 32][0], 5); write(&font[0][0], 1); ++s; } } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::print(const char *s, unsigned char m) { unsigned char c; while(*s) { c = font[*s - 32][0] ^ m; write(&c, 1); c = font[*s - 32][1] ^ m; write(&c, 1); c = font[*s - 32][2] ^ m; write(&c, 1); c = font[*s - 32][3] ^ m; write(&c, 1); c = font[*s - 32][4] ^ m; write(&c, 1); write(&m, 1); ++s; } } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::printv(unsigned char x, unsigned char y, char *s) { while(*s) { pos(x, y); ++y; write(&font[*s - 32][0], 5); write(&font[0][0], 1); ++s; } } static const unsigned char num11x16[19][11 * 2] = { 0x00,0xF0,0xFC,0xFE,0x06,0x02,0x06,0xFE,0xFC,0xF0,0x00, // 0 0x00,0x07,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x07,0x00, 0x00,0x00,0x08,0x0C,0xFC,0xFE,0xFE,0x00,0x00,0x00,0x00, // 1 0x00,0x20,0x20,0x20,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x00, 0x00,0x0C,0x0E,0x06,0x02,0x02,0x86,0xFE,0x7C,0x38,0x00, // 2 0x00,0x30,0x38,0x3C,0x36,0x33,0x31,0x30,0x30,0x38,0x00, 0x00,0x0C,0x0E,0x86,0x82,0x82,0xC6,0xFE,0x7C,0x38,0x00, // 3 0x00,0x18,0x38,0x30,0x20,0x20,0x31,0x3F,0x1F,0x0E,0x00, 0x00,0x00,0xC0,0x20,0x18,0x04,0xFE,0xFE,0xFE,0x00,0x00, // 4 0x00,0x03,0x02,0x02,0x02,0x22,0x3F,0x3F,0x3F,0x22,0x02, 0x00,0x00,0x7E,0x7E,0x46,0x46,0xC6,0xC6,0x86,0x00,0x00, // 5 0x00,0x18,0x38,0x30,0x20,0x20,0x30,0x3F,0x1F,0x0F,0x00, 0x00,0xC0,0xF0,0xF8,0xFC,0x4C,0xC6,0xC2,0x82,0x00,0x00, // 6 0x00,0x0F,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x0F,0x00, 0x00,0x06,0x06,0x06,0x06,0x06,0xC6,0xF6,0x3E,0x0E,0x00, // 7 0x00,0x00,0x00,0x30,0x3C,0x0F,0x03,0x00,0x00,0x00,0x00, 0x00,0x38,0x7C,0xFE,0xC6,0x82,0xC6,0xFE,0x7C,0x38,0x00, // 8 0x00,0x0E,0x1F,0x3F,0x31,0x20,0x31,0x3F,0x1F,0x0E,0x00, 0x00,0x78,0xFC,0xFE,0x86,0x02,0x86,0xFE,0xFC,0xF8,0x00, // 9 0x00,0x00,0x00,0x21,0x21,0x31,0x1D,0x1F,0x0F,0x03,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : 0x00,0x0E,0x0E,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // . 0x00,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x00,0x00,0x00,0x00, // / 0x00,0x30,0x0C,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, // - 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x00,0x18,0x3C,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xF0,0xF8,0x0C,0x06,0x02,0x02,0x02,0x02,0x0E,0x0C,0x00, // C 0x03,0x07,0x0C,0x18,0x10,0x10,0x10,0x10,0x1C,0x0C,0x00, 0xFE,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00, // F 0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFE,0xFE,0x40,0xE0,0xB0,0x18,0x0C,0x06,0x02,0x00,0x00, // K 0x1F,0x1F,0x00,0x00,0x01,0x03,0x06,0x0C,0x18,0x10,0x00 }; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::pd12(unsigned n, unsigned x, unsigned y) { pos(x, y); write(num11x16[n], 11, lcd_data); pos(x, ++y); write(num11x16[n] + 11, 11, lcd_data); } } // namespace
  23. Like
    jsolarski reacted to JWoodrell in "Joystick 430" SNES to USB with the launchpad (proto boosterpack)   
    well as my first little project using the mecrimus interface  I have finished a working interface to take a SNES controller into the PC USB port.
     
    I am using the 32.767 kHz self adjusting version of mecrimus that oPossum recoded.
     
    anyway  the SNES controller is basically a 16bit shift register that originally ran at 5V on the SNES, but runs just as happy at the 3.6 that the MSP spits out.
     
    this version of the interface uses Timer1_A3 to generate a 6us 50% PWM signal to drive the clock line on the shift register.  IT works by setting up a 17 step state machine and "enabling" the timer into "up mode".  each time interrupt it steps the state machine forward and reads the next bit and the clock from the timer drives the next bit out.  There was some interference issues because when a USB packet interrupted the cycle, the timer continued to run.  the only way i got around it was to disable the interrupts during the polling sequence (it only takes 98us so it doesn't mess with the USB link.  The SNES timing is a 12us latch pulse high, then a 6us low, 6 us high clock signal polling at 60Hz.  I am running it twice as fast (6 latch, 3 low, 3 high) polling at 120Hz and its working fine, you can probaly drive the shift register much faster than that, but it there wouldn't be any benefit.
     
    anyway here is a
    of me playing with it...  i apologize for rambling a bit but that is just my nature
     
    The wiring diagram is simple, there are only 5 wires to the controller.
    White - VCC (5V on SNES, but it doesn't complain at 3.6)
    Yellow - P2.1 (Data Clock )
    Orange - P2.0 (Data Latch)
    Red - P1.4 (Serial Data from Controller)
    Brown - GND
     
    (for the controller only, the USB wiring is seperate, and is using my USB interface board i have been working on, although any wiring that works with mecrimus should work.)
     
    I am going to clean up and play with it a little more, Here is how the code is at this point, but it will continue to change and evolve, but have fun
    Joystick_430.zip
  24. Like
    jsolarski got a reaction from sirri in Few General Questions About Launchpad   
    1-The internal thermometer is a seperate chip on launchpad or a feature in 2553 chip?
     
    It is a feature that is part of the ADC, and also SDA on the msp430
     
     
    2-Does internal clock works stand alone (apart from launchpad) ?
     
    What do you mean by stand alone and do you mean the DCO? if you do mean the DCO, yes it is stand alone and run with bare minimum code and in theory you can use the msp430 as a clock generator, as I did to run a 300 baude modem and ref clock
     
    3-Can we supply msp430xx chip standalone with a 3V battery cell? (I can't find LM1086 3.3V voltage regulator in my city)
     
    Yes you can power it by a 3v coin cell, I have also ran it on 2 AA/AAA batteries, or add a third to get 3.6v
     
    4- What is the priority order while coding (energia) among libraries, functions, main code ?
     
    I have no clue, I dont use energia
  25. Like
    jsolarski reacted to touch in Manchester decoding   
    Here's some code I wrote in a hurry to test out some alarm system modules I got on eBay... If memory serves me right they used some sort of PT2262 encoder (it seemed like a chinese knockoff clone) that generates a 16us sync code pulse and then uses Manchester encoding for the data.
     
    The code's pretty sloppy but it worked for what I was testing and I guess I used the "analog style" that jpnorair was talking about.
    #include <msp430g2553.h> #include <stdio.h> void startTimerA(void){ TAR = 0; TACTL = TASSEL_2 + MC_2; } void stopTimerA(void){ TACTL = TASSEL_2 + MC_0; } void main(void) { //Kill WDT and setup clocks WDTCTL = WDTPW + WDTHOLD; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; P1DIR |= 0x01; P1IES &= ~BIT4; // P1.4 Hi/lo edge P1IFG &= ~BIT4; // P1.4 IFG cleared P1IE |= BIT4; // P1.4 interrupt enabled P1SEL = BIT1 + BIT2; P1SEL2 = BIT1 + BIT2; UCA0CTL1 |= UCSSEL_2; UCA0BR0 = 104; UCA0BR1 = 0; UCA0MCTL = UCBRS0; UCA0CTL1 &= ~UCSWRST; _BIS_SR(LPM4_bits + GIE); // Enter LPM4 w/interrupt } // Port 1 interrupt service routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { if(P1IFG & BIT4){ int sync = 0; while((P1IN & BIT4)){} startTimerA(); while(!(P1IN & BIT4)){} sync = TAR; stopTimerA(); if(sync > 14500 && sync < 16700){ int j = 0; char bitcnt = 7; char byte = 0; char data[3] = {0,0,0}; for(j=0; j < 24; j++){ int low = 0; int high = 0; startTimerA(); while(P1IN & BIT4){} high = TAR; stopTimerA(); startTimerA(); while(!(P1IN & BIT4)){} low = TAR; stopTimerA(); if(low > 1200 && high > 300){ data[byte] |= (0 << bitcnt); } else if(low > 300 && high > 1200){ data[byte] |= (1 << bitcnt); }else { } if(bitcnt == 0){ bitcnt = 7; byte++; }else{ bitcnt--; } } while (!(IFG2&UCA0TXIFG)); UCA0TXBUF = data[0]; while (!(IFG2&UCA0TXIFG)); UCA0TXBUF = data[1]; if(data[0] == 0xFD && data[1] == 0x4F){ P1OUT ^= 0x01; } if(data[0] == 0xFF && data[1] == 0xF5){ P1OUT ^= 0x01; } } P1IFG &= ~0x10; } }
×
×
  • Create New...