Jump to content
43oh

lastaid

Members
  • Content Count

    73
  • Joined

  • Last visited

Reputation Activity

  1. Like
    lastaid got a reaction from bluehash in [ ENDED ] Nov 2013 - Jan 2014 - 43oh Project of the Month Contest   
    Hey is it ok to join this with a project i already posted? Have not used it for any contests ^^
     
    http://forum.43oh.com/topic/4262-annoy-a-tron-20/
     
    Have fun!
  2. Like
    lastaid reacted to piglet in My first ever electronics or micrcontroller project: Radio Word clock   
    I'm mostly a lurker on this forum, and watch in somewhat bemused awe at the things you folks manage to create. I'm right at the bottom of a massive learning curve with very little time to climb up it.
     
    Still, I'm very happy with my first ever electronics or microcontroller project. 
     
    It's a word clock inspired by an image of a commercial product I bumped into on the internet.
     
    Parts list:
     
    1) A cheap frame from our local hobby shop
     
    2) An http://www.pvelectronics.co.uk/index.php?main_page=product_info&products_id=2'>






  3. Like
    lastaid reacted to RobG in Saving data to flash on power down   
    Here is a simple solution to the problem I had, saving data when power goes down.
    There are two parts needed, a diode (1N4148) and a capacitor (~47uF.)
    The way it works, you isolate main power from MCU and connect capacitor on the MCU's side.
    One of the pins is connected to the main power and will trigger an interrupt.
    In the interrupt routine, we will be saving data to flash.
    This is a simple proof of concept, the final code should include low voltage detection for situations like dying battery.
     

     


     

    #include "msp430g2231.h" unsigned int data = 0; unsigned int * const savedDataPtr = (unsigned int *)(0x1000); void main(void) { WDTCTL = WDTPW + WDTHOLD; P1DIR &= ~BIT1; P1IE |= BIT1; P1IES |= BIT1; P1IFG &= ~BIT1; P1REN |= BIT1; P1OUT &= ~BIT1; P1DIR |= BIT0; P1OUT |= BIT0; data = *savedDataPtr; if(data == 0xFFFF) data = 100; unsigned int counter = data; _bis_SR_register(GIE); while(1) { counter = data; while(counter > 0) { _delay_cycles(1000); counter--; } P1OUT ^= BIT0; } } // Port 1 interrupt service routine #pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { P1OUT &= ~BIT0; data += 100; // Save value FCTL2 = FWKEY + FSSEL0 + FN1; FCTL1 = FWKEY + ERASE; FCTL3 = FWKEY; *savedDataPtr = 0; FCTL1 = FWKEY + WRT; *savedDataPtr = data; FCTL1 = FWKEY; FCTL3 = FWKEY + LOCK; P1IFG &= ~BIT1; }
  4. Like
    lastaid got a reaction from GeekDoc in Annoy A Tron 2.0   
    I might need to completly rework this thing. It seems like a problem you might only confronted with in warfare, but if a friend finds this annoyatron and deploys it in your flat, which is way messier due to electronic projects and part bins lying around, you're fucked.
     
    i am currently thinking about making an enclosure that is conductive, uses a pin with cap touch capabilities to check if the device was found and then writes a certain value to flash which disables the annoyatron even if it is restartet. that way only someone with a programmer could re-use it.
     
    this on the other hand might interfere with the low power idea, but i don't have any idea how much energy touch i/o actually eats.
     
    any suggestions?
     
    lastaid
  5. Like
    lastaid got a reaction from GeekDoc in Annoy A Tron 2.0   
    Hey ,
     
    Ok, i am currently building 2 kinds of annoyatrons, one being very small an having a high annoy frequency ( delay between beeps) and the other one a huge annoyatron that rarely beebs but is insanly loud and has oversized batteries because i was afraid that a coincell might not provide enough juice and the mcu would brownout.
     
    the big version can be attached to anything metal thanks to a harddrive donored magnet. the small one will fit in a matchbox so it can be hidden in plain sight.
     
    http://youtu.be/90sXqgu-0XA here is a video of the breadboard circuit in action, the beep is somewhere around 0:53 and might not be audible on some speakers.
     
    still wondering how much power this circuit really draws.
     
    -lastaid



  6. Like
    lastaid got a reaction from abecedarian in Annoy A Tron 2.0   
    Hey ,
     
    Ok, i am currently building 2 kinds of annoyatrons, one being very small an having a high annoy frequency ( delay between beeps) and the other one a huge annoyatron that rarely beebs but is insanly loud and has oversized batteries because i was afraid that a coincell might not provide enough juice and the mcu would brownout.
     
    the big version can be attached to anything metal thanks to a harddrive donored magnet. the small one will fit in a matchbox so it can be hidden in plain sight.
     
    http://youtu.be/90sXqgu-0XA here is a video of the breadboard circuit in action, the beep is somewhere around 0:53 and might not be audible on some speakers.
     
    still wondering how much power this circuit really draws.
     
    -lastaid



  7. Like
    lastaid got a reaction from bluehash in Annoy A Tron 2.0   
    Hey ,
     
    Ok, i am currently building 2 kinds of annoyatrons, one being very small an having a high annoy frequency ( delay between beeps) and the other one a huge annoyatron that rarely beebs but is insanly loud and has oversized batteries because i was afraid that a coincell might not provide enough juice and the mcu would brownout.
     
    the big version can be attached to anything metal thanks to a harddrive donored magnet. the small one will fit in a matchbox so it can be hidden in plain sight.
     
    http://youtu.be/90sXqgu-0XA here is a video of the breadboard circuit in action, the beep is somewhere around 0:53 and might not be audible on some speakers.
     
    still wondering how much power this circuit really draws.
     
    -lastaid



  8. Like
    lastaid reacted to oPossum in tone generator on MSP430 g2553   
    /*     *** NOTE: THIS IS LICENSED (C)OPYRIGHTED SOFTWARE - DO NOT REMOVE THE FOLLOWING 20 LINES ***         Copyright (C) 2013  Kevin Timmerman     This program is free software: you can redistribute it and/or modify     it under the terms of the GNU General Public License as published by     the Free Software Foundation, either version 3 of the License, or     (at your option) any later version.     This program is distributed in the hope that it will be useful,     but WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     GNU General Public License for more details.     You should have received a copy of the GNU General Public License     along with this program.  If not, see <http://www.gnu.org/licenses/>         Revision History     ----------------     001 2013.05.10     Written for doomedeggplant who is to lazy to do his homework     */ #include <msp430.h> #include <stdint.h> static uint32_t gpi(unsigned n){     static const uint32_t nt[]={         0x19F10C37,0x1B7BF1E9,0x1D1E52F3,0x1ED994C9,0x20AF3220,0x22A0BC34,         0x24AFDC18,0x26DE542B,0x292E0191,0x2BA0DDCE,0x2E390075,0x30F8A0F2};     static const unsigned f=116;unsigned o=0;while(n<f)n+=12,++o;return nt[n-f]>>o; }static volatile uint32_t pi=0,pa=0; static volatile int32_t t; static void p(const uint8_t *b,const uint8_t*const e,int s,const uint8_t m){     while(P1IN&BIT3);t=10;while(b!=e){P1OUT&=~m;pa=pi=0;t+=13115L;while(t>0);         P1OUT|=m;pi=gpi(*;t+=32787L;while(t>0);b+=s;}P1OUT&=~m;pa=pi=0; }void main(void){     WDTCTL=WDTPW|WDTHOLD;DCOCTL=0;BCSCTL1=CALBC1_16MHZ;DCOCTL=CALDCO_16MHZ;     P1DIR=~BIT3&~BIT1;P1REN=BIT3;P1OUT=BIT2|BIT3;P1SEL=BIT4|BIT1;     TA0CCR0=(16000000L/(1L<<16))-1;TA0CTL=TASSEL_2|MC_1;     TA0CCTL0|=CCIE;_enable_interrupts();     for(;{static const uint8_t z[]="<=>?@ABCDEF"; p(z,z+sizeof(z)-1,1,BIT6);p(z+sizeof(z)-2,z-1,-1,BIT0);} } #pragma vector=TIMER0_A0_VECTOR __interrupt void timer_a0_isr(void){(pa&(1UL<<31))?(P1OUT|=BIT5):(P1OUT&=~BIT5);pa+=pi;--t;} Extra credit: http://forum.43oh.com/topic/2047-rtttl-ring-tone-text-transfer-language-player/?p=17515
  9. Like
    lastaid got a reaction from bluehash in Annoy A Tron 2.0   
    Hey guys
     
    Prank Wars started early this year, so i tried  to improve upon my old annoyatron.
     
    main differences are: only one unified timer interrupt using WDT and WDT_ADLY_1000 and the possibility to put the thing into sleep mode e.g. you can set a time in hours minutes and seconds until the annoyatron becomes active. good for hiding.
     
    my main concerns are :
     
    is there any way to improve the WDT timer accuracy without using ACLK is the code energy efficient? how much current does it eat, i don't have a scope and cannot check things like that how would one immitate a locust chirp ? any feedback is welcome
    #include "msp430g2231.h" #define PIEZO BIT6 #define LED1 BIT0 #define TRUE 1 #define FALSE 0 unsigned short lfsr = 0xACE1u; short hours = 0; short minutes = 10; short seconds = 0; short sleeping = TRUE; unsigned int getRnd (void); void timer (void); void initPWM (void); unsigned i=0; int LPMMode = 0; void main(void) { BCSCTL3 |= LFXT1S_2; // Set VLO WDTCTL = WDT_ADLY_1000; // Set WDT to timer mode at 1000ms, with VLO this is 2740ms IE1 |= WDTIE; // Enable WDT+ interrupt P1DIR |= PIEZO + LED1; // P1.2 PWM output/P1.6 constant output P1OUT = 0; unsigned int delay = 1; while(TRUE) { if (sleeping) { P1OUT ^= LED1; } else { P1OUT ^= LED1; } if (i>delay && !sleeping ) { CCTL1 = OUTMOD_6; // Start P1.2 PWM output // WDTCTL = WDT_ADLY_250; // Reset WDT+ timer to 250ms, with VLO source this is 685ms LPMMode = 0; _BIS_SR(LPM0_bits + GIE); // Go to sleep CCTL1 = OUTMOD_0; i=0; delay = (getRnd() >> 7); } LPMMode = 3; _BIS_SR(LPM3_bits + GIE);// Enter LPM3 w/ interrupt } } // WDT+ ISR for time between beeps and reset for beep length #pragma vector=WDT_VECTOR __interrupt void watchdog_timer (void) { if (sleeping) { LPMMode = 0; i = 0; // keeps or counter from overflowing // without having to put more stuff into the isr seconds -= 3; if ( seconds <= 0) { // count down timer until deployment // we are compensating for the LARGELY inaccurate vlo seconds = 60; if (minutes--<= 0) { minutes = 60; if (hours-- <= 0) { sleeping = seconds = minutes = hours = FALSE; P1SEL |= PIEZO; CCR0 = 42; // Set PWM parameters, CCR0 is PWM Period/2 CCR1 = 21; // Duty cycle TACTL = TASSEL_2 + MC_3; } } } } else { i++; } if(LPMMode == 3) _BIC_SR_IRQ(LPM3_bits); else if(LPMMode == 0) _BIC_SR_IRQ(LPM0_bits); } unsigned int getRnd () { lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xB400u); return lfsr; } thanks, 
     
     
    lastaid
     
    main.c
  10. Like
    lastaid reacted to ElGuille in gscope   
    I needed to be able to watch signals from hundreds of Hz  to 10Khz . While reading the msp430 family manual found the Data Transfer Controller (DTC) that can be put to work with the ADC . 
     
    So the original launchscope by NJC streams data one sample at a time , and that is why it is so slow . So using the DTC we can actually get near the 200Ksps . 
     
    So I use an array of 200 integers (400 Bytes . I didn't want to leave the launchpad without ram, just 512B for the msp430g2553


  11. Like
    lastaid reacted to LariSan in 43oh Secret Santa - 2012   
    I'm so happy that it got to you (I got a little nervous that the shipper didn't get it out on time).
    It's one of the books I'll never get rid of and it looked like you were starting to go beyond just programming and into designing boards :-)
    I hope you enjoy it!
  12. Like
    lastaid got a reaction from LariSan in 43oh Secret Santa - 2012   
    Hey,
     
    sorry for being way too late, though about fixing my camera first, but this will not happen so i will present to you stock images
     

     
    I've already read a few chapters of this wonderful book and cannot imagine anything better suited for me then this book [ finally understood opamps ].
    But who was my secret santa? Thank you alot, as a beginner and Computer Science rather then Electronics student, this is really helpful.
     
     
    sorry for being so late, 
     
    lastaid
     
    @bluehash hope you like it. I fixed up the screen and might even added an slightly improved soundport. Did it arrive unharmed? I could even imagine a project for you, reverse engineer the External Port Protocol and implement an AI enemy ;-)
  13. Like
    lastaid got a reaction from LariSan in 43oh Secret Santa - 2012   
    Thank you Larisan for this wonder, as well as thoughful gift A friend, studying electronical engineering, took a look at it and said "If you have the knowledge in this book, you are an engineering god".
     
    Thank you
  14. Like
    lastaid got a reaction from bluehash in 43oh Secret Santa - 2012   
    Hey,
     
    sorry for being way too late, though about fixing my camera first, but this will not happen so i will present to you stock images
     

     
    I've already read a few chapters of this wonderful book and cannot imagine anything better suited for me then this book [ finally understood opamps ].
    But who was my secret santa? Thank you alot, as a beginner and Computer Science rather then Electronics student, this is really helpful.
     
     
    sorry for being so late, 
     
    lastaid
     
    @bluehash hope you like it. I fixed up the screen and might even added an slightly improved soundport. Did it arrive unharmed? I could even imagine a project for you, reverse engineer the External Port Protocol and implement an AI enemy ;-)
  15. Like
    lastaid 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.
  16. Like
    lastaid got a reaction from cubeberg in MSP430 Sewable - any interest?   
    would love this, might motivate my girlfriend
  17. Like
    lastaid got a reaction from 1HzCoder in MSP430 Annoyatron   
    hey brian
     
    i just played with your source a little. i really like the annoyatron, wanted to plant one on a friend for quite some time.
    i made a little change which would make it completly impossible for someone to anticipate a beep.
    it uses a prng to generate the delays rrather then an array, this way its way less predictable.
    maximum delay is capped to 511 seconds using the bitshift [ from the 16bit unsigned to a more reasonable value ]
     
    have fun
     

    #include "msp430g2231.h" #define PIEZO BIT6 unsigned short lfsr = 0xACE1u; unsigned period = 0; unsigned int getRnd (void); int i=0; void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT P1DIR |= PIEZO; // P1.5 output CCTL0 = CCIE; // CCR0 interrupt enabled CCR0 = 32767; TACTL = TASSEL_1 + MC_1; // ACLK, upmode P1OUT = 0x00; unsigned int delay = 10; while(1) { if (i>delay) { P1OUT ^= PIEZO; // Toggle P1.5 long z = 65000; // Delay do (z--); while (z != 0); P1OUT ^= PIEZO; i=0; delay = getRnd() >> 7; } _BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interrupt } } // Timer A0 interrupt service routine #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) { i++; _BIC_SR_IRQ(LPM3_bits); } unsigned int getRnd () { lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xB400u); ++period; return lfsr; }
  18. Like
    lastaid reacted to oPossum in 24x16 text on VGA using Launchpad w/ G2553   
    This is derived from NTSC/PAL video text display using launchpad. video_vga.asm is a drop in replacement for video.asm.
     

     
    The sync timing is for 640x480 60 Hz VGA mode. A 330 ohm resistor must be used on all video lines (R/G/B) because they are analog signals with a max allowed voltage of about 1 volt. Only one of the R/G/B lines can be driven directly from the MSP430 due to current limitations. A buffer such as 74AHC125 could be used to drive all three if desired.
     
    Wiring

    Gnd ------------ Ground [5, 6, 7, 8, 10] P1.5 ----------- Vertical Sync [14] P1.6 ----------- Horizontal Sync [13] P1.7 ---[330]--- Video out (R [1], G [2] or B [3])
     
    video_vga.asm
    ;
    ; Copyright © 2011, 2012 Kevin Timmerman
    ;
    ; This program is free software: you can redistribute it and/or modify
    ; it under the terms of the GNU General Public License as published by
    ; the Free Software Foundation, either version 3 of the License, or
    ; (at your option) any later version.
    ;
    ; This program is distributed in the hope that it will be useful,
    ; but WITHOUT ANY WARRANTY; without even the implied warranty of
    ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    ; GNU General Public License for more details.
    ;
    ; You should have received a copy of the GNU General Public License
    ; along with this program. If not, see .
    ;
     
    .cdecls C, LIST, "msp430g2553.h"
     
    .text
    .def video_init ; void video_init(void); - Initialize video generation
    .def field_timer ; extern int field_timer; - Decremented at each vsync
    .def vblank ; Vertical blanking flag
    .ref text ; Text buffer
    .ref font ; Font 8 x 12, grouped by row
    ;
    ;
    .bss sync_state, 2 ; Sync state
    .bss sync_lines, 2 ; Lines until next sync state
    .bss video_state, 2 ; Video generation state
    .bss vblank, 2 ; Vertical blanking flag
    .bss field_timer, 2 ; Decrement at vsync
    .bss text_ptr, 2 ; Text buffer pointer
    .bss font_ptr, 2 ; Font pointer
     
     
    ; --- Ideal VGA 640 x 480 60 Hz Timing ---
    ; Pixel clock 25.175 MHz
    ; Horizontal 31.47 kHz (pix / 800, negative sync)
    ; Vertical 59.94 Hz (pix / 420000, negative sync)
    ; - Horizontal timing (line)
    ; Scanline part Pixels Time [
  19. Like
    lastaid reacted to oPossum in Software Real Time Clock (RTC) - two methods   
    The Launchpad comes with a 32.768 kHz crystal that can be used when timing more precise than the DCO is needed. The crystal frequency is useful for simple timing tasks, such as a RTC, because it is a power of 2. That allows a simple cascade of 15 flip-flops to create a 1 pulse per second time base. It is common for microcontroller timers to have prescalers, postscalers and/or preset divisors that are simply a tap on the flip-flip chain. The watchdog timer in the MSP430 is an example of a timer with power of 2 presets (64, 512, 8192, 32768). TimerA units have a prescaler with power of 2 presets (1, 2, 4, 8).
     
    The sample code in this post uses the watchdog timer to create an interrupt that occurs once per second. TimerA can also be used to do this. One of the advantages of using TimerA is the ability to change the preset +/- 1 every N cycles to allow for calibration and temperature compensation of the crystal. I chose to use the watchdog timer so that TimerA was free to be used for alarm tones or PWM backlight control.
     

     
    Using the C standard library time functions for a RTC
    The C standard library provides several functions for working with real time. The function prototypes are in time.h. The type time_t is typically an integer type that is in units of 1 second. It doesn't have to be that, but usually is. The epoch is usually January 1, 1970 for "unix time." Be aware that CCS uses an epoch of January 1, 1900 and time_t is unsigned rather than signed. I assume GCC uses the more common unix time epoch and time_t is signed.
     
    Since time_t is in units of 1 second, the ISR for timekeeping is trivial...

    #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // ++tt; // Increment time_t } //
     
    To display the time it can be converted to a tm structure that has elements for hours, minutes, day, month, ect. There are two functions to do this: gmtime() and localtime(). gmtime() converts to UTC, and localtime converts to the time zone for the set locale. Both functions take a time_t and return a pointer to a static tm struct.
     
    To set the time the mktime() function will convert a tm struct to a time_t value. It will also determine day of week and day or year for you.
     
    Benefits
    Tivial ISR. Simple and efficient.
    Portable code - the C standard library time functions work on almost any device with a C compiler.
    Easy to calulate time deltas - use ordinary integer math on time_t values.
    Easy to compare times using <, >, ==, etc.
    Compact representation of time (32 bit time_t typically) is good for timestamps of data logs.
    Some file systems (not FAT unfortunately) use time_t as for timestamps.
     
    Concerns
    Converting from time_t to tm struct takes quite a few clock cycles, so not good for low power (battery powered) systems.
    Time functions take up quite a bit of flash - will not fit in G2211 for example.
     
    Software model of a hardware RTC
    Hardware real time clocks typically have counters for seconds, minutes, hours, ect. Each counter will reset at the appropriate
    limit - 60 seconds, 24 hours, ect. This approch can be use for a software RTC. The ISR has more code than the previous version...

    #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // if(++t.tm_sec > 59) { // Increment seconds, check for overflow t.tm_sec = 0; // Reset seconds if(++t.tm_min > 59) { // Increment minutes, check for overflow t.tm_min = 0; // Reset minutes if(++t.tm_hour > 23) { // Increment hours, check for overflow t.tm_hour = 0; // Reset hours ++t.tm_yday; // Increment day of year if(++t.tm_wday > 6) // Increment day of week, check for overflow t.tm_wday = 0; // Reset day of week // Increment day of month, check for overflow if(++t.tm_mday > dim[t.tm_mon][is_leap_year(t.tm_year + 1900)]) { t.tm_mday = 1; // Reset day of month if(++t.tm_mon > 11) { // Increment month, check for overflow t.tm_mon = 0; // Reset month t.tm_yday = 0; // Reset day of year ++t.tm_year; // Increment year } // - year } // - month } // - day } // - hour } // - minute } //
     
    Most of the time the ISR will just increment the seconds member and return. The worst case is at the end of the year when the year is incremented and all other counters are reset to inital values.
     
    There is no need for any conversion for display of the time or setting the time. Be aware that day of week and day of year must be explicity set and can be out-of-sync if not properly set.
     
    Benefits
    No conversion function needed for display of time or setting of time.
    Small code size. Fits in G2211.
    High efficiency is good for battery powered applications.
    Use of tm struct provides some familiarity to those who have used the C standard library functions.
     
    Concerns
    No easy to way calulate time delta.
    No support for time zones / localization.
    Time comparison (for alarms) requires more MCU cycles because several structure members require comparason rather than just a long integer.
     


    This sample code can be configured to use either of the two methods descibed by (un)commenting the "#define USE_STDLIB_TIME" in main.c
     
    main.c

    #include #include #include #include "rtc.h" #include "lcd.h" //#define USE_STDLIB_TIME // Use functions in time.h void show_time(const struct tm *t) // Show time on LCD { static const char *dow[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; int x, w; const char *d; if(t->tm_hour < 10) { x = -1; lcd_fill(0, 1, 10, 2, 0); } else { x = 4; lcd_fill(0, 1, 4, 2, 0); lcd_pd12(t->tm_hour / 10, x, 1); } lcd_pd12(t->tm_hour % 10, x + 11, 1); lcd_pd12(11, x + 22, 1); lcd_pd12(t->tm_min / 10, x + 27, 1); lcd_pd12(t->tm_min % 10, x + 38, 1); lcd_pd12(11, x + 49, 1); lcd_pd12(t->tm_sec / 10, x + 54, 1); lcd_pd12(t->tm_sec % 10, x + 65, 1); lcd_fill(x + 76, 1, 8 - x, 2, 0); if(t->tm_mon < 9) { x = -4; lcd_fill(0, 3, 7, 2, 0); } else { x = 1; lcd_fill(0, 3, 1, 2, 0); lcd_pd12((t->tm_mon + 1) / 10, x, 3); } lcd_pd12((t->tm_mon + 1) % 10, x + 11, 3); lcd_pd12(13, x + 22, 3); lcd_pd12(t->tm_mday / 10, x + 30, 3); lcd_pd12(t->tm_mday % 10, x + 41, 3); lcd_pd12(13, x + 52, 3); lcd_pd12(t->tm_year %100 / 10, x + 60, 3); lcd_pd12(t->tm_year % 10, x + 71, 3); lcd_fill(x + 82, 3, 2 - x, 2, 0); d = dow[t->tm_wday]; w = strlen(d) * 6; x = (84 - w) >> 1; lcd_fill(0, 5, x, 1, 0); lcd_print(d, x, 5); x += w; lcd_fill(x, 5, 84 - x, 1, 0); } // struct tm ts; // Time structure time_t tt; // Time in seconds since epoch // // #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // #ifdef USE_STDLIB_TIME // ++tt; // Increment time_t #else // rtc_tick(&ts); // Increment tm struct #endif // __bic_SR_register_on_exit(LPM0_bits); // Wakeup main code } // // void main(void) // { // WDTCTL = WDTPW | WDTHOLD; // Disable watchdog reset // lcd_init(); // Init LCD lcd_clear(0); // lcd_print("MSP430 RTC", 12, 0); // // // 32 kHz xtal loading //BCSCTL3 = XCAP_1; // 6 pF (default) BCSCTL3 = XCAP_2; // 10 pF //BCSCTL3 = XCAP_3; // 12.5 pF // WDTCTL = WDTPW | WDTTMSEL | WDTCNTCL | WDTSSEL; // Use WDT as interval timer IE1 |= WDTIE; // Enable WDT interrupt _EINT(); // Enable interrupts // // Set initial time - there is no UI for this ts.tm_hour = 13; // Hour ts.tm_min = 37; // Minute ts.tm_sec = 42; // Second ts.tm_mon = 3; // Month (0 based!) ts.tm_mday = 20; // Day of Month ts.tm_year = 2012 - 1900; // Year ts.tm_wday = 5; // Day of Week - Not used by mktime() ts.tm_yday = 0; // Not used by mktime() ts.tm_isdst = 0; // DST flag - Not used by rtc_tick() // #ifdef USE_STDLIB_TIME // Convert tm struct to time_t tt = mktime(&ts); // #endif // // for(; { // for-ever #ifdef USE_STDLIB_TIME // show_time(localtime(&tt)); // Convert time_t to tm struct and show on LCD #else // show_time(&ts); // Show time on LCD #endif // __bis_SR_register(LPM0_bits + GIE); // Sleep until WDT interrupt } // } //
     
    rtc.h

    void rtc_tick(struct tm *t);
     
    rtc.c - Software model of hardware RTC

    #include static int is_leap_year(const int y) { if(y & 3) return 0; // Not divisible by 4 switch(y % 400) { // Divisible by 100, but not by 400 (1900, 2100, 2200, 2300, 2500, 2600) case 100: case 200: case 300: return 0; } return 1; // Divisible by 4 and !(100 and !400) } void rtc_tick(struct tm *t) { static const signed char dim[12][2] = { // Number of days in month for non-leap year and leap year 31, 31, // January 28, 29, // February 31, 31, // March 30, 30, // April 31, 31, // May 30, 30, // June 31, 31, // July 31, 31, // August 30, 30, // September 31, 31, // October 30, 30, // November 31, 31 // December }; // // if(++t->tm_sec > 59) { // Increment seconds, check for overflow t->tm_sec = 0; // Reset seconds if(++t->tm_min > 59) { // Increment minutes, check for overflow t->tm_min = 0; // Reset minutes if(++t->tm_hour > 23) { // Increment hours, check for overflow t->tm_hour = 0; // Reset hours ++t->tm_yday; // Increment day of year if(++t->tm_wday > 6) // Increment day of week, check for overflow t->tm_wday = 0; // Reset day of week // Increment day of month, check for overflow if(++t->tm_mday > dim[t->tm_mon][is_leap_year(t->tm_year + 1900)]) { t->tm_mday = 1; // Reset day of month if(++t->tm_mon > 11) { // Increment month, check for overflow t->tm_mon = 0; // Reset month t->tm_yday = 0; // Reset day of year ++t->tm_year; // Increment year } // - year } // - month } // - day } // - hour } // - minute } //
     
    lcd.h

    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; void lcd_send(const unsigned char *cmd, unsigned len, const lcd_cmd_type type); void lcd_home(void); void lcd_pos(unsigned char x, unsigned char y); void lcd_clear(unsigned char x); void lcd_init(void); void lcd_fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z); void lcd_print(const char *s, unsigned x, unsigned y); void lcd_pd12(unsigned n, unsigned x, unsigned y);
     
    lcd.c

    #include #include "lcd.h" //static const unsigned TXD = BIT1; static const unsigned RXD = BIT2; static const unsigned SWITCH = BIT3; static const unsigned LCD_CLK = BIT5; static const unsigned LCD_BACKLIGHT = BIT6; static const unsigned LCD_DATA = BIT7; static const unsigned LCD_DC = BIT0; // PORT2 static const unsigned LCD_CE = BIT1; // PORT2 void lcd_send(const unsigned char *cmd, unsigned len, const lcd_cmd_type type) { register unsigned mask; P2OUT &= ~LCD_CE; do { mask = 0x0080; do { if(*cmd & mask) { P1OUT &= ~LCD_CLK; P1OUT |= LCD_DATA; } else { P1OUT &= ~(LCD_CLK | LCD_DATA); } P1OUT |= LCD_CLK; mask >>= 1; } while(!(mask & 1)); if(!type) P2OUT &= ~LCD_DC; if(*cmd & mask) { P1OUT &= ~LCD_CLK; P1OUT |= LCD_DATA; } else { P1OUT &= ~(LCD_CLK | LCD_DATA); } P1OUT |= LCD_CLK; P2OUT |= LCD_DC; if(!(type & 2)) ++cmd; } while(--len); P2OUT |= LCD_CE; } static const unsigned char home[] = { 0x40, 0x80 }; void lcd_home(void) { lcd_send(home, sizeof(home), lcd_command); } void lcd_pos(unsigned char x, unsigned char y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); } void lcd_clear(unsigned char x) { lcd_home(); lcd_send(&x, 504, lcd_data_repeat); lcd_home(); } void lcd_init(void) { static const unsigned char init[] = { 0x20 + 0x01, // function set - extended instructions enabled 0x80 + 64, // set vop (contrast) 0 - 127 0x04 + 0x02, // temperature control 0x10 + 0x03, // set bias system 0x20 + 0x00, // function set - chip active, horizontal addressing, basic instructions 0x08 + 0x04 // display control - normal mode }; P1REN = RXD | SWITCH; P1DIR = LCD_CLK | LCD_BACKLIGHT | LCD_DATA; P1OUT = LCD_CLK | RXD | SWITCH | LCD_BACKLIGHT; P2REN = 0; P2DIR = LCD_DC | LCD_CE; P2OUT = LCD_CE; __delay_cycles(20000); P2OUT |= LCD_DC; __delay_cycles(20000); lcd_send(init, sizeof(init), lcd_command); } void lcd_fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z) { unsigned yy = y + h; unsigned char c[2]; c[0] = 0x80 | x; for(;y < yy; ++y) { c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); lcd_send(&z, w, lcd_data_repeat); } } static const unsigned char font6x8[96][5] = { 0x00, 0x00, 0x00, 0x00, 0x00, // 20 32 0x00, 0x00, 0x5F, 0x00, 0x00, // 21 33 ! 0x00, 0x07, 0x00, 0x07, 0x00, // 22 34 " 0x14, 0x7F, 0x14, 0x7F, 0x14, // 23 35 # 0x24, 0x2A, 0x7F, 0x2A, 0x12, // 24 36 $ 0x23, 0x13, 0x08, 0x64, 0x62, // 25 37 % 0x36, 0x49, 0x56, 0x20, 0x50, // 26 38 & 0x00, 0x08, 0x07, 0x03, 0x00, // 27 39 ' 0x00, 0x1C, 0x22, 0x41, 0x00, // 28 40 ( 0x00, 0x41, 0x22, 0x1C, 0x00, // 29 41 ) 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, // 2A 42 * 0x08, 0x08, 0x3E, 0x08, 0x08, // 2B 43 + 0x00, 0x40, 0x38, 0x18, 0x00, // 2C 44 , 0x08, 0x08, 0x08, 0x08, 0x08, // 2D 45 - 0x00, 0x00, 0x60, 0x60, 0x00, // 2E 46 . 0x20, 0x10, 0x08, 0x04, 0x02, // 2F 47 / 0x3E, 0x51, 0x49, 0x45, 0x3E, // 30 48 0 0x00, 0x42, 0x7F, 0x40, 0x00, // 31 49 1 0x42, 0x61, 0x51, 0x49, 0x46, // 32 50 2 0x21, 0x41, 0x49, 0x4D, 0x33, // 33 51 3 0x18, 0x14, 0x12, 0x7F, 0x10, // 34 52 4 0x27, 0x45, 0x45, 0x45, 0x39, // 35 53 5 0x3C, 0x4A, 0x49, 0x49, 0x30, // 36 54 6 0x41, 0x21, 0x11, 0x09, 0x07, // 37 55 7 0x36, 0x49, 0x49, 0x49, 0x36, // 38 56 8 0x06, 0x49, 0x49, 0x29, 0x1E, // 39 57 9 0x00, 0x00, 0x14, 0x00, 0x00, // 3A 58 : 0x00, 0x00, 0x40, 0x34, 0x00, // 3B 59 ; 0x00, 0x08, 0x14, 0x22, 0x41, // 3C 60 < 0x14, 0x14, 0x14, 0x14, 0x14, // 3D 61 = 0x00, 0x41, 0x22, 0x14, 0x08, // 3E 62 > 0x02, 0x01, 0x51, 0x09, 0x06, // 3F 63 ? 0x3E, 0x41, 0x5D, 0x59, 0x4E, // 40 64 @ 0x7C, 0x12, 0x11, 0x12, 0x7C, // 41 65 A 0x7F, 0x49, 0x49, 0x49, 0x36, // 42 66 B 0x3E, 0x41, 0x41, 0x41, 0x22, // 43 67 C 0x7F, 0x41, 0x41, 0x41, 0x3E, // 44 68 D 0x7F, 0x49, 0x49, 0x49, 0x41, // 45 69 E 0x7F, 0x09, 0x09, 0x09, 0x01, // 46 70 F 0x3E, 0x41, 0x49, 0x49, 0x7A, // 47 71 G 0x7F, 0x08, 0x08, 0x08, 0x7F, // 48 72 H 0x00, 0x41, 0x7F, 0x41, 0x00, // 49 73 I 0x20, 0x40, 0x41, 0x3F, 0x01, // 4A 74 J 0x7F, 0x08, 0x14, 0x22, 0x41, // 4B 75 K 0x7F, 0x40, 0x40, 0x40, 0x40, // 4C 76 L 0x7F, 0x02, 0x1C, 0x02, 0x7F, // 4D 77 M 0x7F, 0x04, 0x08, 0x10, 0x7F, // 4E 78 N 0x3E, 0x41, 0x41, 0x41, 0x3E, // 4F 79 O 0x7F, 0x09, 0x09, 0x09, 0x06, // 50 80 P 0x3E, 0x41, 0x51, 0x21, 0x5E, // 51 81 Q 0x7F, 0x09, 0x19, 0x29, 0x46, // 52 82 R 0x26, 0x49, 0x49, 0x49, 0x32, // 53 83 S 0x01, 0x01, 0x7F, 0x01, 0x01, // 54 84 T 0x3F, 0x40, 0x40, 0x40, 0x3F, // 55 85 U 0x1F, 0x20, 0x40, 0x20, 0x1F, // 56 86 V 0x3F, 0x40, 0x38, 0x40, 0x3F, // 57 87 W 0x63, 0x14, 0x08, 0x14, 0x63, // 58 88 X 0x03, 0x04, 0x78, 0x04, 0x03, // 59 89 Y 0x61, 0x51, 0x49, 0x45, 0x43, // 5A 90 Z 0x00, 0x7F, 0x41, 0x41, 0x41, // 5B 91 [ 0x02, 0x04, 0x08, 0x10, 0x20, // 5C 92 '\' 0x00, 0x41, 0x41, 0x41, 0x7F, // 5D 93 ] 0x04, 0x02, 0x01, 0x02, 0x04, // 5E 94 ^ 0x80, 0x80, 0x80, 0x80, 0x80, // 5F 95 _ 0x00, 0x03, 0x07, 0x08, 0x00, // 60 96 ' 0x20, 0x54, 0x54, 0x54, 0x78, // 61 97 a 0x7F, 0x28, 0x44, 0x44, 0x38, // 62 98 b 0x38, 0x44, 0x44, 0x44, 0x28, // 63 99 c 0x38, 0x44, 0x44, 0x28, 0x7F, // 64 100 d 0x38, 0x54, 0x54, 0x54, 0x18, // 65 101 e 0x00, 0x08, 0x7E, 0x09, 0x02, // 66 102 f 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // 67 103 g 0x7F, 0x08, 0x04, 0x04, 0x78, // 68 104 h 0x00, 0x44, 0x7D, 0x40, 0x00, // 69 105 i 0x00, 0x20, 0x40, 0x40, 0x3D, // 6A 106 j 0x00, 0x7F, 0x10, 0x28, 0x44, // 6B 107 k 0x00, 0x41, 0x7F, 0x40, 0x00, // 6C 108 l 0x7C, 0x04, 0x78, 0x04, 0x78, // 6D 109 m 0x7C, 0x08, 0x04, 0x04, 0x78, // 6E 110 n 0x38, 0x44, 0x44, 0x44, 0x38, // 6F 111 o 0xFC, 0x18, 0x24, 0x24, 0x18, // 70 112 p 0x18, 0x24, 0x24, 0x18, 0xFC, // 71 113 q 0x7C, 0x08, 0x04, 0x04, 0x08, // 72 114 r 0x48, 0x54, 0x54, 0x54, 0x24, // 73 115 s 0x04, 0x04, 0x3F, 0x44, 0x24, // 74 116 t 0x3C, 0x40, 0x40, 0x20, 0x7C, // 75 117 u 0x1C, 0x20, 0x40, 0x20, 0x1C, // 76 118 v 0x3C, 0x40, 0x30, 0x40, 0x3C, // 77 119 w 0x44, 0x28, 0x10, 0x28, 0x44, // 78 120 x 0x4C, 0x90, 0x90, 0x90, 0x7C, // 79 121 y 0x44, 0x64, 0x54, 0x4C, 0x44, // 7A 122 z 0x00, 0x08, 0x36, 0x41, 0x00, // 7B 123 { 0x00, 0x00, 0x77, 0x00, 0x00, // 7C 124 | 0x00, 0x41, 0x36, 0x08, 0x00, // 7D 125 } 0x02, 0x01, 0x02, 0x04, 0x02, // 7E 126 ~ 0x00, 0x06, 0x09, 0x09, 0x06, // 7F 127 degrees }; void lcd_print(const char *s, unsigned x, unsigned y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 | y; lcd_send(c, sizeof(c), lcd_command); while(*s) { lcd_send(&font6x8[*s - 32][0], 5, lcd_data); lcd_send(&font6x8[0][0], 1, lcd_data); ++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 }; void lcd_pd12(unsigned n, unsigned x, unsigned y) { unsigned char c[2]; c[0] = 0x80 | x; c[1] = 0x40 + y; lcd_send(c, 2, lcd_command); lcd_send(num11x16[n], 11, lcd_data); c[1] = 0x41 + y; lcd_send(c, 2, lcd_command); lcd_send(num11x16[n] + 11, 11, lcd_data); }
  20. Like
    lastaid got a reaction from kylej1050 in MSP430 Annoyatron   
    hey brian
     
    i just played with your source a little. i really like the annoyatron, wanted to plant one on a friend for quite some time.
    i made a little change which would make it completly impossible for someone to anticipate a beep.
    it uses a prng to generate the delays rrather then an array, this way its way less predictable.
    maximum delay is capped to 511 seconds using the bitshift [ from the 16bit unsigned to a more reasonable value ]
     
    have fun
     

    #include "msp430g2231.h" #define PIEZO BIT6 unsigned short lfsr = 0xACE1u; unsigned period = 0; unsigned int getRnd (void); int i=0; void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT P1DIR |= PIEZO; // P1.5 output CCTL0 = CCIE; // CCR0 interrupt enabled CCR0 = 32767; TACTL = TASSEL_1 + MC_1; // ACLK, upmode P1OUT = 0x00; unsigned int delay = 10; while(1) { if (i>delay) { P1OUT ^= PIEZO; // Toggle P1.5 long z = 65000; // Delay do (z--); while (z != 0); P1OUT ^= PIEZO; i=0; delay = getRnd() >> 7; } _BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interrupt } } // Timer A0 interrupt service routine #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) { i++; _BIC_SR_IRQ(LPM3_bits); } unsigned int getRnd () { lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xB400u); ++period; return lfsr; }
  21. Like
    lastaid got a reaction from tom_launch_bav in Eclipse plugin for mspdebug and msp430-gcc   
    Please don't beat me, but will this work for windows as well?
     
    I normally use CCS, but having an opensource alternative and using the mspgcc would be preferable. A easy to setup 100% opensource IDE for linux, windows and macos would be a big step into the right direction.
  22. Like
    lastaid reacted to SugarAddict in 14.5 megs of #43oh IRC goodness...   
    So these are the combined logs that I have for #43oh irc channel up to a little bit ago... Be afraid.
     
    4.26mb zip
  23. Like
    lastaid reacted to SirZusa in TLC5940 - "Full Implementation"   
    hi there, as i already said in another thread i was working on the code for controlling the TLC5940. here it is!
     
    100% working. specification-sheet i used to code this: http://www.ti.com/lit/sw/slvc106/slvc106.pdf
     


    [*:1o0bnvvd]supports DC
    [*:1o0bnvvd]supports Grayscale
    [*:1o0bnvvd]recommendet implementation from the Programming Flow Chart
    [*:1o0bnvvd]does not support EEPROM-programming (cause you will need 22 Volts for this)
    [*:1o0bnvvd]actually does not support "Use DC from EEPROM-mode"
    [*:1o0bnvvd]LOD-Check not implemented for now ... but i think i will do this soon if i find more literature on this
     

    /*** TLC5940 ***/ #include "msp430g2553.h" #include "stdbool.h" // How many TLC's daisy-chained #define n 2 /*** Ports ***/ // STATUS-LED #define PORT_STATUS_LED P1OUT #define PIN_STATUS_LED BIT0 // BLANK - to pin 23 of every TLC5940 #define PORT_BLANK P1OUT #define PIN_BLANK BIT3 // XLAT - to pin 24 of every TLC5940 #define PORT_XLAT P1OUT #define PIN_XLAT BIT4 // SCLK - to pin 25 of every TLC5940 #define PORT_SCLK P1OUT #define PIN_SCLK BIT5 // SIN - to pin 26 of first TLC5940 #define PORT_SIN P1OUT #define PIN_SIN BIT6 // GSCLK - to pin 18 of every TLC5940 #define PORT_GSCLK P1OUT #define PIN_GSCLK BIT7 // DCPRG - to pin 19 of every TLC5940 #define PORT_DCPRG P2OUT #define PIN_DCPRG BIT3 // VPRG - to pin 27 of every TLC5940 #define PORT_VPRG P2OUT #define PIN_VPRG BIT4 /*** DO NOT EDIT BELOW ***/ #define x (n * 16) /*** Brightness-Correction ***/ const int pwm_table[256] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,26,28,30,32,34,36,38,40,42, 44,46,48,50,52,55,58,61,64,67,70,73,76,79,82,85,88,91,94,97,100,103,106,110,114,118,122,126,130, 134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,195,200,205,210,215,220,225,230,235, 240,245,250,255,260,265,270,275,280,285,290,297,304,311,318,325,332,339,346,353,360,367,374,381, 388,395,402,409,416,423,430,437,444,451,458,467,476,485,494,503,512,521,530,539,548,557,566,575, 584,593,602,611,626,641,656,671,686,701,716,731,746,761,776,791,806,821,836,851,866,881,896,916, 936,956,976,996,1016,1036,1056,1076,1096,1116,1136,1156,1176,1196,1221,1246,1271,1296,1321,1346, 1371,1396,1421,1446,1471,1496,1526,1556,1586,1616,1646,1676,1706,1736,1766,1796,1826,1856,1886, 1921,1956,1991,2026,2061,2096,2131,2166,2201,2236,2271,2306,2341,2376,2411,2446,2481,2516,2551, 2586,2621,2656,2691,2726,2761,2796,2832,2868,2904,2940,2976,3012,3048,3084,3120,3156,3192,3228, 3266,3304,3342,3380,3418,3456,3494,3532,3572,3612,3652,3692,3737,3782,3827,3872,3917,3962,4007,4095 }; // holds the actual DC-data for each channel char dc_data[x] = {63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63}; /*** Variables ***/ // first PWM-cycle after Dot Correction Data has changed? bool FirstCycleFlag; // holds the actual PWM-data for each channel int gs_data[x]; /*** small userdefined Functions ***/ // useful macros #define setLow(port, pin) { port &= ~pin; } #define setHigh(port, pin) { port |= pin; } #define pulse(port, pin) { setHigh(port, pin); setLow(port, pin); } #define toggle(port, pin) { port ^= pin; } /*** transfer DC-data to our TLC5940's ***/ void send_DC() { // DCPRG - dont use DC-EEPROM setHigh(PORT_DCPRG, PIN_DCPRG); // VPRG - set Dot Correction Input setHigh(PORT_VPRG, PIN_VPRG); // Reset Counter int Counter = 0; // clock in Dot Correction Data for (; { // Counter > n * 96 - 1 // 6 Bits * 16 Channels = 96 if (Counter > (n * 96 - 1)) { pulse(PORT_XLAT, PIN_XLAT); break; } else { // Set SIN to DC Data[Counter] // MSB first if ((dc_data[Counter / 6] >> (5 - (Counter % 6))) & 0x01) { setHigh(PORT_SIN, PIN_SIN); } else { setLow(PORT_SIN, PIN_SIN); } pulse(PORT_SCLK, PIN_SCLK); Counter++; } } // dont save to EEPROM - so we finish here // set FirstCycleFlag to true FirstCycleFlag = true; } /*** transfer PWM-data to our TLC5940's ***/ void send_GS() { if (FirstCycleFlag == true) { setLow(PORT_VPRG, PIN_VPRG); } // Reset Counters int GSCLK_Counter = 0; int Data_Counter = 0; setLow(PORT_BLANK, PIN_BLANK); // clock in PWM Data for (; { if (GSCLK_Counter > 4095) { setHigh(PORT_BLANK, PIN_BLANK); pulse(PORT_XLAT, PIN_XLAT); if (FirstCycleFlag == true) { pulse(PORT_SCLK, PIN_SCLK); } FirstCycleFlag = false; break; } else { // 12 Bit * 16 Channels = 192 if (Data_Counter > (n * 192 - 1)) { pulse(PORT_GSCLK, PIN_GSCLK); GSCLK_Counter++; } else { // Set SIN to GS Data[Counter] // MSB first if ((gs_data[Data_Counter / 12] >> (11 - (Data_Counter % 12))) & 0x01) { setHigh(PORT_SIN, PIN_SIN); } else { setLow(PORT_SIN, PIN_SIN); } pulse(PORT_SCLK, PIN_SCLK); Data_Counter++; pulse(PORT_GSCLK, PIN_GSCLK); GSCLK_Counter++; } } } } /*** Our main program ***/ void main(void) { // stop WDT - WDTPW is the password needed for every write and then tell watchdog to hold WDTCTL = WDTPW | WDTHOLD; BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; // initialize the ports connected to the TLC's // set ports to output-direction P1DIR |= (PIN_STATUS_LED|PIN_BLANK|PIN_XLAT|PIN_SCLK|PIN_SIN|PIN_GSCLK); P1OUT = 0x00; P2DIR |= (PIN_DCPRG|PIN_VPRG); P2OUT = 0x00; // initialize TLC5940 setLow(PORT_GSCLK, PIN_GSCLK); setLow(PORT_SCLK, PIN_SCLK); setLow(PORT_DCPRG, PIN_DCPRG); setHigh(PORT_VPRG, PIN_VPRG); setLow(PORT_XLAT, PIN_XLAT); setHigh(PORT_BLANK, PIN_BLANK); // force first cycle send_DC(); send_GS(); // enable interrupts __bis_SR_register(GIE); while(1) { // load gs-data here // update PWM-data permanently send_GS(); } }
  24. Like
    lastaid reacted to bluehash in TLC5940 - "Full Implementation"   
    Thanks for sharing your code, SirZusa.
  25. Like
    lastaid got a reaction from Brian2898 in MSP430 Annoyatron   
    hi again,
     
    fixed my code ^^
     
    brian: do you use piezo that automaticly generates a sound? because your code just turn port 1.6 on, then off without any PWM
     
    second: as the code uses timerA, can i use a value line device with only one timer to generate sound AND timing with one Timer ?
     
    anyway, here is my code, which is completly based on brians code
     
    https://gist.github.com/1049184
     
    it uses an http://en.wikipedia.org/wiki/Linear_feedback_shift_register to generate the delays and silly wait loops to generate PWM.
     
    have fun
×
×
  • Create New...