Jump to content
43oh

zeke

Members
  • Content Count

    1,782
  • Joined

  • Last visited

  • Days Won

    102

Reputation Activity

  1. Like
    zeke reacted to spirilis in I'm struggling with the CC3200   
    Huh-
    "We are now shipping a complimentary PRE-RELEASE copy of our up-coming book "Mastering the FreeRTOS Real Time Kernel - a Hands-On Tutorial Guide" with every purchased copy of "Using the FreeRTOS Real TIme Kernel"."
     
    Almost wondering if I should buy the Cortex-M3 version of the book + reference soon for giggles.  The bonus prereleased book appears to walk you through a lot of hand-holding: http://www.realtimeengineers.com/ReferencedDownloads/Table-Of-Contents-Mastering-the-FreeRTOS-Real-Time-Kernel.pdf
     
    edit: Meh, decided to go ahead and buy it.  Didn't bother with the $20 reference manual since I still have an old (non-printable/requires password PDF to view) copy anyhow.  They have to manually critique each order and they're in the UK so I probably won't see it until tomorrow.  I am going to look into having them printed & bound.
     
    See this is the kind of documentation TI-RTOS really needs.  Extensive book material going from basic to master.
  2. Like
    zeke reacted to Rei Vilo in I'm struggling with the CC3200   
    Two pointers for using RTOS on Energia with commented examples:
    LaunchPad MSP432: RTOS for Everyone Exploring RTOS with Galaxia Galaxy is a library I've developed for Energia. It encapsulates RTOS elements as objects for an easier use.
    Threads: SWI, Task Synchronisation: Event, Semaphore, Mailbox, Timer, Clock
  3. Like
    zeke got a reaction from spirilis in I'm struggling with the CC3200   
    Cool!
     
    I found a TI wiki page listing a bunch of sample programs for the CC3200:
     
    http://processors.wiki.ti.com/index.php/CC32xx_SDK_Sample_Applications
     
    It lists several freeRTOS based programs demonstrating various functions.
     
    Maybe freeRTOS *is* the way to go?
  4. Like
    zeke reacted to monsonite in A Tiny Plug In Computer using MSP430FR2xxx devices   
    OK I started on the build this evening - should get this flashing a LED before sunrise.
     

     
     
    And I did! - code loaded by SBW, Uart connected, SIMPL running & LED flashing by 2am!
     

     
     
    Ken
     
     
  5. Like
    zeke reacted to Fred in A Tiny Plug In Computer using MSP430FR2xxx devices   
    One thing the TRF7970 has taught me is that QFN is a PITA. 
    Well, I'm actually off to meet monsonite on the pub. Let's hope that doesn't adversely affect his ability to get an LED blinking by sunrise!
  6. Like
    zeke reacted to DanielPHuber in Servo programming   
    Hi,
    I tried my hand for the first time on a servo and my experience may be helpful to other people.
     
    Servos are controlled by the length of a pulse. This pulse is repeated ca. every 20mS. The pulse length can vary coarsly between 1 and 2 mS. The pulse length determines the rotation angle. If the servo starts up, it goes to a middle position, corresponding to a ca. 1.5 mS pulse. For shorter pulses the servo turns in one direction, for longer pulses to the other. The range is limited, mostly to +/- 90 degree, the accurate values depend on the servo, as does the min/max widths. Mine had a range of a bit more than 180 degree for a min pulse width of 680 uS and a max width of 2.62 mS. However, you should not use these values but allow for some safety margin. Otherwise the motor may just not reach (e.g. due to slip or play) the position and the motor tries hard and gets hot.
     
    Most servos have 3 wires that are color coded from bright to dark, the color may change. The brightest is the signal pin where the pulses are fed. The middle one, mostly red, goes to Plus and the darkest one (brown, black..) goes to ground.
     
    Energia comes with a helpful server library. There an object: "Servo" is declared. You initiated the server by the method "attach". It comes in 2 varieties  (assuming we declared an object "myservo"):
     
    myservo.attach(pinNo);
    myservo.attach(pinNo,minVal,maxVal);
     
    where pinNo means the launchpad pin number of the pin used to control the servo. min/maxVal are the minimal/maximal pulse width you want to use. This is not clearly described in the library and confused me bit. In further commands you can confortably deal with degrees beween 0 and 180. The library will transform the degree values into pulse widths, where 0 degree corresponds to the minimal pulse width and 180 degree to the max you specified. If you do not specify min/max values, some default values are used. In may case the lower default value could not be reached and the motor got hot. Therefore, it is better to determine correct values and specify these, using the second form of "attach".
     
    After initialization the servo goes to the 90 degree position. To send it to the 0 degree positio you would write:
    myservo.write(0);
    My servo did not respond quit linear. To send it to the 90 degree position I had to say 83 degree. 
     
    Here is a small test program:
     


    // test for 9g Servo 
    // 1. Button press -> 0 degree
    // 2. Button press -> 90 degree. Due due nonlinearity we need 83 degree
    // 3. Button press -> 180 degree.
    // 4. Button press -> 90  degree.


    #define sig P1_4  // signal for servo
    #define but P1_3  // button
    #define minWidth 770  // min pulse width in uSec of servo (680 allowed)
    #define maxWidth 2595 // max pulse width in uSec of servo (2620 allowed)
    #include <Servo.h>


    Servo myservo;


    void setup()
    {
       myservo.attach(sig,minWidth,maxWidth);
       pinMode(but, INPUT_PULLUP);
    }


    void loop()
    {  
       while (digitalRead(but));
       myservo.write(0); delay(500);
       while (digitalRead(but));  
       myservo.write(83);delay(500);
       while (digitalRead(but));  
       myservo.write(180);delay(500);
       while (digitalRead(but));
       myservo.write(83); delay(500);
    }

     
    Note that due to nonlinearity of the servo I need to specify 83 degree for a 90 degree rotation.
     
    For test purposes you may power the servo directly from the launchpad (provided you do not have a monster servo with a hugh current consumption). In the enclosed picture I control the servo from launchpad pin P1_4 and power it directly from the launchpad.
     
    Have fun, Daniel

  7. Like
    zeke reacted to monsonite in SIMPL - A Tiny Language for MSP430   
    Here's an interview with Ward Cunningham, from Portland OR - who developed the first Wiki - almost exactly 21 years ago.  (March 25th 1995)
     
    He is also the creator of Txtzyme which was the inspiration for SIMPL.
     
    http://portlandcreatives.co/portfolio/ward-cunningham/
     
     

     
    Ken
  8. Like
    zeke reacted to tonyp12 in tiny msp430 preemptive multitasking system   
    Tested on G2553 Launchpad with IAR, I recommend G2955 with 1K RAM if you want more than 3 task
    #include "msp430.h" #include "common.h" //=========================(C) Tony Philipsson 2016 ======================= funcpnt const taskpnt[]={ task1, task2, task3, // <- PUT YOUR TASKS HERE }; const int stacksize[tasks] = {28}; // a blank value defaults to 24 stack words //========================================================================= int taskstackpnt[tasks]; unsigned int taskdelay[tasks]; char taskrun; int main( void ) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer if (CALBC1_8MHZ != 0xff){ // erased by mistake? BCSCTL1 = CALBC1_8MHZ; // Set DCO to factory calibrate 1MHz DCOCTL = CALDCO_8MHZ; } int* multistack = (int*) __get_SP_register(); int i=0; while(i<tasks-1){ int j = stacksize[i]; if (!j) j = 24; multistack -= j; *(multistack) = (int) taskpnt[++i]; // prefill in PC *(multistack-1) = GIE; // prefill in SR taskstackpnt[i] = (int) multistack-26; // needs 12 dummy push words } WDTCTL = WDTPW+WDTTMSEL+WDTCNTCL; // 4ms interval at 8MHz smclk IE1 |= WDTIE; __bis_SR_register(GIE); asm ("br &taskpnt"); // indirect jmp to first task } //============= TASK SWITCHER ISR ============= #pragma vector = WDT_VECTOR __raw __interrupt void taskswitcher(void) { asm ("push R15\n push R14\n push R13\n push R12\n" "push R11\n push R10\n push R9\n push R8\n" "push R7\n push R6\n push R5\n push R4"); taskstackpnt[taskrun] = __get_SP_register(); if (++taskrun == tasks) taskrun = 0; __set_SP_register(taskstackpnt[taskrun]); asm ("pop R4\n pop R5\n pop R6\n pop R7\n" "pop R8\n pop R9\n pop R10\n pop R11\n" "pop R12\n pop R13\n pop R14\n pop R15"); } #include "msp430.h" #include "common.h" __task void task1(void){ P1DIR |= BIT0; while(1){ __delay_cycles(800000); P1OUT |= BIT0; __delay_cycles(800000); P1OUT &=~BIT0; } } #include "msp430.h" #include "common.h" __task void task2(void){ P1DIR |= BIT6; while(1){ __delay_cycles(1200000); P1OUT |= BIT6; __delay_cycles(1200000); P1OUT &=~BIT6; } } #include "msp430.h" #include "common.h" unsigned int fibo(int); __task void task3(void){ int temp = 0; while(1){ fibo(++temp); } } unsigned int fibo(int n){ if (n < 2) return n; else return (fibo(n-1) + fibo(n-2)); } #ifndef COMMON_H_ #define COMMON_H_ #define tasks (sizeof(taskpnt)/2) __task void task1(void); __task void task2(void); __task void task3(void); typedef __task void (*funcpnt)(void); #endif
  9. Like
    zeke reacted to dubnet in New Project: Temperature Measuring with MLX90615 [please help, this is my first project]   
    When you looked at the TI documents did you see these two?
     
    http://www.ti.com/tool/msp430-smbus
     
    http://www.ti.com/lit/ug/tidu741/tidu741.pdf
  10. Like
    zeke reacted to yyrkoon in Have you experienced a chilling effect?   
    @@zeke
     
    Well my questions were more rhetorical than anything, meant for you to answer for yourself. I do not really place judgment on people, thats not my place. Despite that I'm very opinionated, and not afraid to show it - It may seem that way. However, with that said, I do not want everyone, or even anyone  to be like me ( would be boring ! ), and I have been known to change my ideas, opinions, and what not based on others ideas . . .but only if it rings true for me.
     
    I still do think we all should still share the basic knowledge related to various hardware discussed here. But there is no reason you, I, or anyone should just give people fully fleshed out ideas, or software without some sort of compensation. That's just not very . . realistic.
     
    I had some guy on the beagleboard.org google groups ask me if the software I designed to read the CANBUS module and "spit" the decoded data out over a websocket to  webrowser client was "anywhere in the open software space". He knew of it because I had mentioned it to someone else. Anyway, my answer very short, sweet, and perhaps even selfish . . ."nope."
     
    EDIT:
     
    Also I'd like to add that I don't keep score, and I'd probably ignore anyone I thought that did. But you talking about oPossum's printf() stuff. Because Rickta, and I used to have mini competitions about printf() this, and printf() that. The really funny part though . . . I was "competing" with Rickta, using his code lol . . .honestly though he was teaching me in a round about way, by letting me toy with his older code while he was writing new, and improved code. I learned a good bit from all that, and had fun too.
     
    I think around this time, I was "hot and heavy" into C++ because of the templatized UART code oPossum wrote / shared, which I modified slightly for my own purposes. But I was so infatuated with it because the code footprint was tiny, and did a whole lot for the amount of code space it took up. Looking back, I still think oPossum's original code was great, and yes, I had fun toying with it. But now days . . . I'm back to learning more heavily towards C again. Mostly because C as a language on it's own is less complex, and less to worry about by comparison.
     
    My point here I suppose condensed, is that I do appreciate various persons sharing code on the forums here, and in the process of them sharing their code / ideas, I had a good deal of fun learning various things that might have otherwise been very "dry" topics.
  11. Like
    zeke got a reaction from yyrkoon in Have you experienced a chilling effect?   
    @@yyrkoon,
     
    Sorry, I've been busy getting ready for a class next week. 
     
    I'm liking everyone's posts because I want them to know that I appreciate their contribution to the discussion. Thank you for yours too!
     
    All of us speak from our own points of view. I spoke up because I was thinking out loud. I do not necessarily believe everything that comes out of my mouth. The intent is to say things out loud, listen to what I am saying then process those things. Are they bad or good, foolish or wise, obvious or insightful?  And so on.  
     
    I posted my thoughts to invite you all into this same process of testing my observations.
     
    My apologies if my suppositions come across as selfish or ignorant.
     
    On the topic of being a teacher, I resonated with the observations that @@Rickta59 and @@spirilis spoke of. It depends upon the context in which things are being shared:
    Does the requestor demand knowledge from the giver (panic approach)? Does the requestor seek wisdom for the application of knowledge (true student)? Does the requestor beg you to solve their problem (profit motivation)? It's up to the giver to respond appropriately from his or her point of view.
     
    Someone called me at my office. He found me via this website. He begged me to solve his msp430 hardware problem. I did. I reckon that I saved him $10,000. Yet that fellow apparently thought my wisdom, knowledge, experience and efforts were not worth anything to him. He did not pay me. He just disappeared into the wind. Shame on me. I will never do that again.
     
    @@yyrkoon, your point about not sharing valued code resonated with me as well. Thank you. I agree. In fact, that is what I have done for the most part. It is true, there are some code wizards here and I have learned from them as well. Yet, I know that I have not put any of their code into my own work. That includes @@oPossum's incredible printf() function and @@RobG's LCD code. Although, in the near future, I may have to ask RobG for permission.
     
    Do I know everything? Not a chance.
     
    Do I learn in a vacuum? No way. I learn from data sheets mostly. If you can't read the data sheet then you're in deep trouble as an Engineer.
     
    Do I copy-paste code from 43oh.com into my own work? I can't remember the last time I did.
     
    Do I share my code here on 43oh.com? Yes. I have shared simplified versions of my code. I rewrite some routines to save the awesome stuff for myself. Case in point, I know that I am holding out on my 1-Wire code. Why? Because I make money with that code. Any code that I have charged someone for is not allowed to be posted online. That's just a personal rule.
     
    But, once, I shared some code here that I did make money with. Someone (I think oPossum) ripped that code up and dismissed its value immediately. I took that personally. I don't like that feeling.  I know it has had value because I got paid for it. My customer's needs were taken care of. I am now careful when considering the sharing of my code.
     
    Do I copy-paste the code that I find online elsewhere?  In general, nope. Typically, I can't use the code that I find online. It usually doesn't work out of the box for my application. Take oPossum's code. To my eyes, he's an absolutely gifted coder who started coding in assembly language (I'm guessing). His c code looks like assembly to me. He appears to think in assembly. I do not. Sometimes I wished that I did! Therefore, I can only learn from the general intention of his routines. My implementations will follow my way of thinking. It's not right or wrong. It's just different. 
     
    As I mentioned from the start, I'm just thinking out loud in order to process my feelings and my observations. I do not claim to know what is right or wrong in all of this. I do claim to be slightly confused but seeking clarity on the matter.
     
    I will continue to contribute here as I can.
    I will keep my mouth shut on topics that I know nothing about.
    I will share my insights and experience as I can.
     
    Hopefully, the panicky students will learn patience.
    Hopefully, the charlatans will get the bum's rush out of this place.
    Hopefully, the eager students will continue to come here to learn.
     
    Personally, I find the eager students a breath of fresh air. I find that they are the ones who learn how to share their learning journey with others who come here.
     
    It is my intent to be a person that gives more than he takes from this community. Forgive me if I have failed at this task. 
  12. Like
    zeke got a reaction from dubnet in Have you experienced a chilling effect?   
    @@yyrkoon,
     
    Sorry, I've been busy getting ready for a class next week. 
     
    I'm liking everyone's posts because I want them to know that I appreciate their contribution to the discussion. Thank you for yours too!
     
    All of us speak from our own points of view. I spoke up because I was thinking out loud. I do not necessarily believe everything that comes out of my mouth. The intent is to say things out loud, listen to what I am saying then process those things. Are they bad or good, foolish or wise, obvious or insightful?  And so on.  
     
    I posted my thoughts to invite you all into this same process of testing my observations.
     
    My apologies if my suppositions come across as selfish or ignorant.
     
    On the topic of being a teacher, I resonated with the observations that @@Rickta59 and @@spirilis spoke of. It depends upon the context in which things are being shared:
    Does the requestor demand knowledge from the giver (panic approach)? Does the requestor seek wisdom for the application of knowledge (true student)? Does the requestor beg you to solve their problem (profit motivation)? It's up to the giver to respond appropriately from his or her point of view.
     
    Someone called me at my office. He found me via this website. He begged me to solve his msp430 hardware problem. I did. I reckon that I saved him $10,000. Yet that fellow apparently thought my wisdom, knowledge, experience and efforts were not worth anything to him. He did not pay me. He just disappeared into the wind. Shame on me. I will never do that again.
     
    @@yyrkoon, your point about not sharing valued code resonated with me as well. Thank you. I agree. In fact, that is what I have done for the most part. It is true, there are some code wizards here and I have learned from them as well. Yet, I know that I have not put any of their code into my own work. That includes @@oPossum's incredible printf() function and @@RobG's LCD code. Although, in the near future, I may have to ask RobG for permission.
     
    Do I know everything? Not a chance.
     
    Do I learn in a vacuum? No way. I learn from data sheets mostly. If you can't read the data sheet then you're in deep trouble as an Engineer.
     
    Do I copy-paste code from 43oh.com into my own work? I can't remember the last time I did.
     
    Do I share my code here on 43oh.com? Yes. I have shared simplified versions of my code. I rewrite some routines to save the awesome stuff for myself. Case in point, I know that I am holding out on my 1-Wire code. Why? Because I make money with that code. Any code that I have charged someone for is not allowed to be posted online. That's just a personal rule.
     
    But, once, I shared some code here that I did make money with. Someone (I think oPossum) ripped that code up and dismissed its value immediately. I took that personally. I don't like that feeling.  I know it has had value because I got paid for it. My customer's needs were taken care of. I am now careful when considering the sharing of my code.
     
    Do I copy-paste the code that I find online elsewhere?  In general, nope. Typically, I can't use the code that I find online. It usually doesn't work out of the box for my application. Take oPossum's code. To my eyes, he's an absolutely gifted coder who started coding in assembly language (I'm guessing). His c code looks like assembly to me. He appears to think in assembly. I do not. Sometimes I wished that I did! Therefore, I can only learn from the general intention of his routines. My implementations will follow my way of thinking. It's not right or wrong. It's just different. 
     
    As I mentioned from the start, I'm just thinking out loud in order to process my feelings and my observations. I do not claim to know what is right or wrong in all of this. I do claim to be slightly confused but seeking clarity on the matter.
     
    I will continue to contribute here as I can.
    I will keep my mouth shut on topics that I know nothing about.
    I will share my insights and experience as I can.
     
    Hopefully, the panicky students will learn patience.
    Hopefully, the charlatans will get the bum's rush out of this place.
    Hopefully, the eager students will continue to come here to learn.
     
    Personally, I find the eager students a breath of fresh air. I find that they are the ones who learn how to share their learning journey with others who come here.
     
    It is my intent to be a person that gives more than he takes from this community. Forgive me if I have failed at this task. 
  13. Like
    zeke reacted to monsonite in SIMPL - A Tiny Language for MSP430   
    Hello All
     
     
     
    My MSP430FR4133 Launchpads turned up this morning and it was quite quick and easy to port SIMPL across to it - from previously on the MSP430G2533
     
    I have included the code below.
     
    The UART is running at 125000 Baud -  a simple binary division of the 8MHz clock.   I use Termite or Terraterm - which will handle these non standard baudrates.
     
    The SPI RAM is connected to USCB0   - see this blogpost for preliminary details.
     
    On the '4133 Launchpad the following connections are needed
     
    MOSI           P5.2
    MISO           P5.3
    SCLK           P5.1
    /RAM_CS    P8.0
     
    http://sustburbia.blogspot.co.uk/2016/03/interfacing-spi-sram-fram-to-msp430.html 
     
     
    I've got the display to display integers <100, with some rather dirty code!
     
     
    In the future I like the look of the new low cost, low pin-out  FRAM based   FR24xx, FR25xx and FR26xx series as potential targets for SIMPL
    // SIMPLEX 2_MSP430FR4133_5 // - inspired by Txtzyme Nano Interpreter - an original idea by Ward Cunningham // An on going Neo-Retro Computing Mission! // Ken Boak March 9th 2016 // SIMPL Interpreter for MSP430FR4133 Launchpad // This version adds 23K256 32Kx8 external SPI RAM, plus hex-dump utlity // With addition of timing routines and other debug // MSP430FR4133 UART, SPI and LCD suport Routines // - codesize is now 4167 bytes // This version for FRAM based MSP430 with MSP430FR4133 Launchpad compiled using Energia // Note - serial uart on P1.1 and P1.2 is running at odd-baud of 100,000 bits/s - to be investigated // This version includes the t and v functions to determine timing tests - note millis is running at 16 times speed! // Any time entered for m or u is multiplied by 16 // Any time printed out from b or c id divided by 16! // There is a debug pin on P1.0 (Green LED) which allows scope probe attachment to confirm times // RAM connections /*         +------U------+ P8.0 /CE    |   23K256    | 3V3 P5.2  MISO   |             | HOLD - pull up to 3V3  NC |             | SCK - P5.1   0V   |             | MOSI - P5.2         +-------------+ */ // Timing // 1,000,000 empty loops in 2.4uS per iteration // 100,000,000 empty loops in 2.4uS per iteration #include <MSP430FR4133.h> #define RXD BIT1 // Receive Data (RXD) at P1.1 #define TXD BIT2 // Transmit Data (TXD) at P1.2 #define RED 0x20 // Red LED is on Bit 6 #define GREEN 0x01 // Green LED is on Bit 0 //#define SS_PIN BIT4 // CS , active low #define SS_PIN BIT0 // CS , active low Port 8.0 #define DEBUG_PIN BIT0 // toggle on and off marking time to write #define DUMMY_BYTE 0xFF // byte we send when we just want to read slave data //#define ssSelect P1OUT &= ~SS_PIN //#define ssDeselect P1OUT |= SS_PIN #define ssSelect P8OUT &= ~SS_PIN #define ssDeselect P8OUT |= SS_PIN #define delay_1ms __delay_cycles(16000) #define bufRead(addr) (*(unsigned char *)(addr)) #define bufWrite(addr, (*(unsigned char *)(addr) = () #define bit0 0x01 // 1 #define bit1 0x02 // 2 #define bit2 0x04 // 4 #define bit3 0x08 // 8 #define bit4 0x10 // 16 #define bit5 0x20 // 32 #define bit6 0x40 // 64 #define bit7 0x80 // 128 #define SR_WRITE_STATUS 0x01 #define SR_WRITE 0x02 #define SR_READ 0x03 #define SR_READ_STATUS 0x05 #define BYTES_TO_STREAM 1024 // should be less <= 32768 #define PATTERN_BYTE_VALUE 65 //--------------------------------------------------------------------------------- // LCD defines #define pos1 4 // Digit A1 - L4 #define pos2 6 // Digit A2 - L6 #define pos3 8 // Digit A3 - L8 #define pos4 10 // Digit A4 - L10 #define pos5 2 // Digit A5 - L2 #define pos6 18 // Digit A6 - L18 const char digit[96] = // Array to hold digits, upper case alpha and punctuation { 0xFC, // "0" 0x60, // "1" 0xDB, // "2" 0xF3, // "3" 0x67, // "4" 0xB7, // "5" 0xBF, // "6" 0xE4, // "7" 0xFF, // "8" 0xF7 // "9" }; //--------------------------------------------------------------------------------- static inline uint8_t RWData(uint8_t value); int spi_rx_data = 0 ; //----------------------------------------------------------------- // This character array is used to hold the User's words - on the '2553 we only have 512 bytes of RAM char array[6][32] = { {"_Hello World, welcome to SIMPL_"}, {"_Mary had a Little Lamb_"}, {"_This is a test message_"}, {"_Hickory, Dickory Dock_"}, {"_twas brillig slithy toves_"}, {"11{kp_ Green Bottles_}"} }; char buf[64]; // Buffer to hold users keyboard entry char num_buf[11]; // long enough to hold a 32 bit long char block_array[33]; // Used to transfer bytes from external RAM and execute x-code // int a = 0; // integer variables a,b,c,d // int b = 0; // int c = 0; // int d = 6; // d is used to denote the digital port pin for I/O operations unsigned long x = 0; // Three gen purpose variables for stack & math operations unsigned long y = 0; unsigned int z = 0; unsigned int ADC_value=0; int hex_value = 0; int dec_value = 0; int decimal_value = 0; char ha = 0; char hex_char; unsigned char in_byte; int len = 32; // the max length of a User word int length = 0; // number of bytes to red/write to SRAM int address = 0 ; // starting address of RAM R/W streamms int RAM_byte =0; // contents of RAM at given location long old_millis=0; long new_millis=0; unsigned long time = 0; char name; char* parray; char* px_array; char* addr; char mode = 0x41; // Sequential mode for SRAM unsigned int num = 0; unsigned int num_val = 0; int j; /* //--------------------------------------------------------------------- // Initialise the USCI B for Master Mode SPI //--------------------------------------------------------------------- // recommended procedure: set UCSWRST, configure USCI, configure ports, activate //--------------------------------------------------------------------- void spi_init(void) { //--------------------------------------------------------------------- // Configure the Clock for 16 MHz BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; //--------------------------------------------------------------------- // Set UCSWRST UCB0CTL1 = UCSWRST; //--------------------------------------------------------------------- // Configure USCI B0 UCB0CTL0 |= UCCKPH + UCMSB + UCMST + UCSYNC; // 3-pin, 8-bit SPI master UCB0CTL1 |= UCSSEL_2; // SMCLK UCB0BR0 |= 2; // 8 MHz SPI-CLK UCB0BR1 = 0; //UCB0MCTL = 0; //--------------------------------------------------------------------- // Configure Ports P1SEL |= BIT5 + BIT6 + BIT7; P1SEL2 |= BIT5 + BIT6 + BIT7; P1DIR |= BIT0 + BIT4 + BIT5 | BIT7; //--------------------------------------------------------------------- // activate UCB0CTL1 &= ~UCSWRST; } */ //-------------------------------------------------------------------------------- // SPI Initialisation for MSP430FR4133 LaunchPad //-------------------------------------------------------------------------------- // P5.3 MISO // P5.2 MOSI // P5.1 SCLK // P8.0 /RAM_CS void spi_init_4133() { // Configure GPIO P8DIR |= BIT0; // For /RAM_CS P5SEL0 |= BIT1 | BIT2 | BIT3; // SCLK, MISO, MOSI pins // Configure USCI_B0 UCB0CTLW0 |= UCSWRST; // **Put state machine in reset** UCB0CTLW0 |= UCMST|UCSYNC|UCCKPH|UCMSB; // 3-pin, 8-bit SPI master // Clock polarity low, MSB UCB0CTLW0 |= UCSSEL_2 ; // SMCLK UCB0BR0 = 0x01; // /2,fBitClock = fBRCLK/(UCBRx+1). UCB0BR1 = 0; // UCB0CTLW0 &= ~UCSWRST; // **Initialize USCI state machine** } //-------------------------------------------------------------------------------- // 23K256 Serial Ram functions //-------------------------------------------------------------------------------- uint8_t SR_getMode(void) { // Read the Mode of the 23K256 ssSelect; // select RWData(SR_READ_STATUS); // 0x05 uint8_t mode = RWData(DUMMY_BYTE); ssDeselect; // de-select return mode; } void SR_setMode(uint8_t mode) { // Write Mode to 23K256 ssSelect; RWData(SR_WRITE_STATUS); // 0x01 RWData(mode); ssDeselect; } static inline void SR_writestream(uint16_t addr) { // Write a stream to 23K256 ssDeselect; // deselect if we are active ssSelect; RWData(0x02); // Send command RWData(addr >> 8); // Send upper address RWData(addr); // Send lower address } static inline void SR_readstream(uint16_t addr) { // Read a stream from 23K256 ssDeselect; ssSelect; RWData(0x03); // Send command RWData(addr >> 8); // Send upper address RWData(addr); // Send lower address } //----------------------------------------------------------------- // SPI Send / Receive static inline uint8_t RWData(uint8_t value) { UCB0TXBUF = value; // while (!(IFG2 & UCB0TXIFG)) {}; // wait for buffer ready while (!(UCB0IFG & UCTXIFG)) {}; // wait for buffer ready // while (!(IFG2 & UCB0RXIFG)); // USCI_B0 RX Received? while (!(UCB0IFG & UCRXIFG)); // USCI_B0 RX Received? spi_rx_data = UCB0RXBUF; // Store received data return spi_rx_data; } //------------------------------------------------------------------------------------ // UART Initialisation // UART provides PC comms on 1.2 and P1.2 - uses USCI A void uart_init_4133(void) { // Configure UART pins P1SEL0 |= BIT0 | BIT1; // set 2-UART pin as second function // Configure UART UCA0CTLW0 |= UCSWRST; UCA0CTLW0 |= UCSSEL__SMCLK; // Baud Rate calculation // 8000000/(16*9600) = 52.083 // Fractional portion = 0.083 // User's Guide Table 14-4: UCBRSx = 0x49 // UCBRFx = int ( (52.083-52)*16) = 1 UCA0BR0 = 4; // 8000000/16/9600 UCA0BR1 = 0x00; UCA0MCTLW = 0x5500 | UCOS16 | UCBRF_1; UCA0CTLW0 &= ~UCSWRST; // Initialize eUSCI } /* void uart_init(void) { P1SEL = RXD + TXD; P1SEL2 = RXD + TXD; UCA0CTL1 |= UCSSEL_2; // SMCLK UCA0BR0 = 156; // 1MHz 9600 UCA0BR1 = 0; // 1MHz 9600 UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1 UCA0CTL1 &= ~UCSWRST; // Initialize USCI state machine } */ //--------------------------------------------------------------------- // UART Primitive Routines uart_putc and uart_get_c unsigned char uart_getc() { // while (!(IFG2&UCA0RXIFG)); // USCI_A0 RX buffer ready? while (!(UCA0IFG&UCRXIFG)); // USCI_A0 RX buffer ready? return UCA0RXBUF; } void uart_putc(unsigned char c) { while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = c; // TX } void uart_puts(const char *str) // Output a string { while(*str) uart_putc(*str++); } //------------------------------------------------------------------------ // Print a long unsigned int number void printlong(unsigned long num) { if (num / (unsigned long)10 != 0) printlong(num / (unsigned long)10); uart_putc((char)(num % (unsigned long)10) + '0'); return; } //--------------------------------------------------------------------------- // Print a CR-LF void crlf(void) // send a crlf { uart_putc(10); // uart_putc(13); } void print_ok() {uart_puts((char *)"OK\n\r"); } //------------------------------------------------------------------------------------ // Initialise the ADC on the '4133 void ADC_init_4133(void) { } /* //------------------------------------------------------------------------------------- // ADC Configuration void ConfigureAdc(void) { ADC10CTL1 = INCH_3 + ADC10DIV_3 ; // Channel 3, ADC10CLK/3 ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE; // Vcc & Vss as reference, Sample and hold for 64 Clock cycles, ADC on, ADC interrupt enable ADC10AE0 |= BIT3; // ADC input enable P1.3 } int ADC_Read(void) { ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start ADC_value = ADC10MEM; return ADC_value; } */ //------------------------------------------------------------------------------------- // mS delay routine void delay_mS(int j) { volatile unsigned long i; while(j) { i = 42; // Delay do (i--); while (i != 0); // busy waiting (bad) j--; } } //--------------------------------------------------------------------------------- void setup(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode // Serial.begin(100000); // initialises timing functions // BCSCTL1 = CALBC1_1MHZ; // Set DCO // DCOCTL = CALDCO_1MHZ; P1DIR = BIT0 + BIT6; // P1.0 and P1.6 are the red+green LEDs P1OUT = BIT0 + BIT6; // All LEDs off uart_init_4133(); // Initialise the '4133 UART for 96000 baud spi_init_4133(); // Initialise the '4133 SPI on USCIB 8MHz clock, master mode uart_puts((char *)"MSP430 SIMPLEX\n\r"); // send opening banner message spi_check(); // Make sure SPI RAM is connected and in the correct streaming mode // P1SEL |= BIT3; // ADC input pin P1.3 ADC_init_4133(); WDTCTL = WDTPW + WDTTMSEL + WDTIS1; // enable watchdog - interval mode parray = &array[0][0]; // parray is the pointer to the first element of code buffer px_array = &block_array[0]; // px_array is pointer to first element of RAM transfered block array delay(1); time = micros(); printlong(time); // used for timing functions crlf(); LCD_print_4133(); } void loop(void) { //------------------------------------------------------------------------------- // Interpreter Loop while(1) { textRead(buf, 64); // This is the endless while loop which implements the SIMPL interpreter - just 3 simple functions textChk(buf); // check if it is a : character for beginning a colon definition textEval(buf); } // end of interpreter loop } // End of main //------------------------------------------------------------------------------- // Language Functions - Words // ------------------------------------------------------------------------------ // Read the character into the buffer void textRead (char *p, byte n) { byte i = 0; while (i < (n-1)) { char ch = uart_getc(); if (ch == '\r' || ch == '\n') break; if (ch >= ' ' && ch <= '~') { *p++ = ch; i++; } } *p = 0; } // --------------------------------------------------------------------------------------------------------- void textChk (char *buf) // Check if the text starts with a colon and if so store in user's word RAM array parray[] { if (*buf == ':') { char ch; int i =0; while ((ch = *buf++)){ if (ch == ':') { uart_putc(*buf); // get the name from the first character uart_putc(10); uart_putc(13); name = *buf ; buf++; } bufWrite((parray + (len*(name-65) +i)),*buf); i++; } x = 1; } } // --------------------------------------------------------------------------------------------------------- void textEval (char *buf) { char *loop; char *start; char ch; unsigned long k = 0; while ((ch = *buf++)) { // Is it a number? switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': x = ch - '0'; while (*buf >= '0' && *buf <= '9') { x = x*10 + (*buf++ - '0'); // If a number store it in "x" } break; //------------------------------------------------------------------------------- // User Words case 'A': // Point the interpreter to the array containing the words case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': textEval(parray + (len*(ch-65))); // Evaluate and execute the User's expression fo RAM break; //--------------------------------------------------------------------------------- // (a - h hijacked for SPI RAM extensions - SIMPLEX!) case 'a': // Address (for writing to RAM) address =(x); break; case 'b': // Block - fetch a block from external memory get_block(x); break; case 'c': // Compile hex_print_2(x); break; case 'd': // HEX Dump - dump x bytes starting at address y hex_dump(y,x); print_ok(); break; /* case 'd': // Decimal Dump dump(y,x); // dump y bytes starting at address x break; */ case 'e': // Execute execute_block(x); break; case 'f': // File // fill y bytes starting at address x with test data spi_fill(y,x); print_ok(); break; case 'g': // Go run_block(); break; case 'n': // Go LCD_display_n(x); break; //-------------------------------------------------------------------------------- // Primitive and User vocabulary defined in this section // Timing & Printing Group case 'p': printlong(x); // print long integer break; case 'q': // print integer with crlf printlong(x); crlf(); break; case 't': time = micros(); printlong(time/16); // used for timing functions crlf(); break; case 'v': time = micros(); printlong(time/16); // used for timing functions crlf(); break; /* case 'd': d = x; break; */ case '_': // Print the string enclosed between underscores eg. _Hello_ while ((ch = *buf++) && ch != '_') { uart_putc(ch); } uart_putc(10); break; case 92 : // ASCII 92 forward slash \ Copy the text enclosed between \ and \ to RAM while ((ch = *buf++) && ch != 92) { uart_putc(ch); } uart_putc(10); put_block(address); break; //---------------------------------------------------------- // Arithmetic Group case '+': x = x+y; break; case '-': x = x-y; break; case '*': x = x*y; break; case '/': x = x/y; break; case '%': x = x%y; break; case 'x': x = x + 1; break; case 'y': y = y + 1; break; //-------------------------------------------------------------------- // Logical Group - provides bitwise logical function between x and y case '&': x = x&y; // Logical AND break; case '|': x = x|y; // Logical OR break; case '^': x = x^y; // Logical XOR break; case '~': x = !x; // Complement x break; case ' ': // Transfer x into second variable y k=y; // Transfer loop counter into k y= x; break; case '#': // Load x with the ASCII value of the next character i.e. 5 = 35H or 53 decimal x=*(buf-2); break; case '$': // print out a number as either a 2 digit or 4 digit Hexadecimal if(x<=255) {hex_print_2(x); break;} hex_print_4(x); break; // ---------------------------------------------------------------------- // Memory Group case '!': // store y = x; break; case '@': // Fetch x = y; break; /* case 'r': // read a byte from RAM bite = bufRead(x); // x = address x = bite; uart_putc(x); // print the character break; case 'q': // read a block of x bytes of RAM at address y for (int i=0; i<x; i++) { bite = bufRead(y+i); // read the array uart_putc(bite); // print the character to the serial port } break; case 'w': // write a byte to RAM address in y, data in x bufWrite(y,x); break; */ //-------------------------------------------------------------------- // Comparison Test and conditional Group case '<': if(x<y){x=1;} // If x<y x= 1 - can be combined with jump j else x=0; break; case '>': if(x>y){x=1;} // If x>y x= 1 - can be combined with jump j else x=0; break; case 'j': // test if x = 1 and jump next instruction if(x==1){*buf++;} break; //---------------------------------------------------------------------------------- // Print out the current word list case '?': // Print out all the RAM parray = &array[0][0]; // reset parray to the pointer to the first element for (int j = 0; j<26; j++) { uart_putc(j+65); // print the caps word name uart_putc(32); // space for (int i=0; i<len; i++) { in_byte = bufRead( parray + (j *len )+i); // read the array uart_putc(in_byte); // print the character to the serial port } crlf(); } for(int i = 0; i <11; i++) // add some spaces to make it more legible on the page { crlf(); } break; //---------------------------------------------------------------------------------------------------- // Conditional Code branch case '[': // The start of a condition test k = x; start = buf; // remember the start position of the test while ((ch = *buf++) && ch != ']') { // get the next character into ch and increment the buffer pointer *buf - evaluate the code } case ']': if (x) { // if x is positive - go around again buf = start; } break; //-------------------------------------------------------------------------- // Case Statement Selection // Select some code from a list separated by commas //5(0p,1p,2p,3p,4p,5p,6p) should select 5 and print it case '(': k = x; // copy x to use as the "phrase counter" // decrement k to see whether to interpret or not while (k) { ch = *buf++; if (ch == ',') { k--;} } break; case ',': k--; // while (k<0) // k < 0 so skip the remaining entries in the list { ch = *buf++; // skip the remaining characters if (ch == ')') {break;} } break; //----------------------------------------------------------------------------------------------------------------------------------------------- // Analogue and Digital Input and Output Group - these add heavily to total - need to be converted to MSP430 case 's': // x = ADC_Read(); // Adds 38 bytes break; /* case 'a': analogWrite(d,x); // adds 340 bytes break; case 'i': x = digitalRead(d); // adds 100 bytes break; case 'o': digitalWrite(d, x%2); // adds 18 bytes break; */ //------------------------------------------------------------------- // Delays Group case 'm': delay(x<<4); break; case 'u': delayMicroseconds(x<<4); break; //--------------------------------------------------------------------- case '{': k = x; loop = buf; while ((ch = *buf++) && ch != '}') { } case '}': if (k) { k--; buf = loop; } break; case 'k': x = k; break; // ----------------------------------------------------------------------------- // Launchpad LED group support for red and green LEDs on entry level LaunchPad case 'w': { P1OUT |= BIT0; } break; case 'r': { P1OUT &= ~BIT0; } break; case 'h': { P1OUT |= BIT6; } break; case 'l': { P1OUT &= ~BIT6; } break; // ---------------------------------------------------------------------- } } } //----------------------------------------------------------------------------- // SPI RAM Extensions to SIMPL Test routines etc //--------------------------------------------------------------------- char RAM_stream_mode() { ssDeselect; delay_1ms; uint8_t chipMode; chipMode = SR_getMode(); // check status register for sequential mode if (chipMode != 0x41) { SR_setMode(0x41); return 0; } return 1; } //--------------------------------------------------------------------------- // Check that the external RAM is present and that it is in Sequential Mode int spi_check() { ssDeselect; delay_1ms; uint8_t chipMode; // make sure there is a 23K256 chip and that // is wired properly and in sequential mode chipMode = SR_getMode(); if (chipMode != 0x41) { SR_setMode(0x41); uart_puts((char *)"SPI RAM not found\n\r"); } else { uart_puts((char *)"32K SPI RAM Connected!\n\r"); } } //-------------------------------------------------------------------------- // RAM mode // Where mode = // 0x01 Byte Mode // 0x81 Page Mode (Page = 32 bytes) // 0x41 Sequential Mode //-------------------------------------------------------------------------- char RAM_byte_mode(char mode) // Set the RAM into the correct mode { ssDeselect; uint8_t chipMode; chipMode = SR_getMode(); // check status register for byte mode if (chipMode != mode) { SR_setMode(mode); return 0; } return 1; } // ----------------------------------------------------------------------------- //spi_fill()- fill the RAM from address with "initial orders" characters // ----------------------------------------------------------------------------- void spi_fill(int address, int length ) // fill { uint16_t i; char storedValue = 0; RAM_stream_mode(); SR_writestream(address); // start writing at address for(j=0; j<6; j++) { for (i = 0; i < 32; ++i) { storedValue = int (array[j][i]); RWData(storedValue); } } } //----------------------------------------------------------------------------------------- void put_block(int address) { uint16_t i; char storedValue = 0; RAM_stream_mode(); SR_writestream(address*32); // start writing at address for (i = 0; i < 32; ++i) { storedValue = int (buf[i]); // copy key buffer to RAM block if(storedValue != 92) // omit opening \ and closing \ { RWData(storedValue); uart_putc(storedValue); } } // ----------------------------------------------------------------------------- // dump the characters from RAM to screen - putting a newline every 64 bytes // ----------------------------------------------------------------------------- void dump(int address, int length) { int i =0; crlf(); // Start with a newline! RAM_stream_mode(); SR_readstream(address); // start reading at address 0 for (i = 0; i < length ; ++i) { if(i%32 == 0) { crlf(); // put a newline every 32 chars printlong(i+ address); // print the line address followed by four spaces uart_putc(0x20); uart_putc(0x20); uart_putc(0x20); uart_putc(0x20); } RAM_byte = RWData(DUMMY_BYTE); if(RAM_byte <= 31) {RAM_byte = '.';} // Make it a full stop for unprintable characters uart_putc(RAM_byte); } } //-------------------------------------------------------------------------------------------- // Generate a familiar hex dump of the RAM area void hex_dump(int address, int length) { crlf(); // Start with a newline! int i =0; SR_readstream(address); // start reading at address 0 for (j = address >>5; j <= (address +length)>> 5 ; ++j) { for (i = 0; i < 32 ; ++i) { if(i== 0) { hex_print_4(j<<5); // print the line address as HEX followed by 2 spaces uart_putc(0x20); uart_putc(0x20); } RAM_byte = RWData(DUMMY_BYTE); // Now read and print the data as numbers // printlong(RAM_byte); hex_print_2(RAM_byte); block_array[i] = RAM_byte; // block_array is a temporary buffer to hold current RAM block uart_putc(0x20); // followed by a space } uart_putc(0x20); // Separate columns with 3 spaces uart_putc(0x20); uart_putc(0x20); for (i = 0; i < 32 ; ++i) // start reading back at address 0 so as to print the characters { RAM_byte = block_array[i]; if(RAM_byte <= 31 || RAM_byte >= 127) {RAM_byte = '.';} // Print a full stop for all unprintable characters uart_putc(RAM_byte); } crlf(); // put a newline every 32 chars } } //----------------------------------------------------------------- // Convert a char into a 2 character hex pair void hex_print_2(int dec_value) { ha = dec_value >> 4; hex_print_char(ha); ha = dec_value - (ha << 4); hex_print_char(ha); } //----------------------------------------------------------------- // Convert an int into into a 4 character hex pair // note all binary mults and divs should use shift ops for efficiency void hex_print_4(unsigned int decimal_value) { int div_value = decimal_value >> 8; hex_print_2(div_value); dec_value = decimal_value - (ha << 8); hex_print_2(dec_value); uart_putc(32); // output a space } void hex_print_char(char hex_value) // decode the A-F numbers { if (ha <=9){hex_char = '0' + ha ;} // Digits 0-9 if (ha >= 10) {hex_char = '7' + ha ;} // Letters A-F uart_putc(hex_char); } //--------------------------------------------------------------------------- // RAM Block routines void get_block(int address) { int i =0; RAM_stream_mode(); SR_readstream(address << 5); // start reading at address for (i = 0; i <32 ; ++i) { RAM_byte = RWData(DUMMY_BYTE); block_array[i] = RAM_byte; // block_array is a temporary buffer to hold current RAM block // uart_putc(RAM_byte); } // crlf(); } //--------------------------------------------------------------------------------------------- void execute_block(int address) // Load a block and execute it { get_block(address); run_block(); } //--------------------------------------------------------------------------------------------- // Point the Interpreter at the code contained in block_array and let it execute it! void run_block() { textEval(px_array); // Evaluate and execute the User's expression fo External RAM } //---------------------------------That's All Folks--------------------------------------------- void LCD_print_4133(void) { // Configure LCD pins SYSCFG2 |= LCDPCTL; // R13/R23/R33/LCDCAP0/LCDCAP1 pins selected LCDPCTL0 = 0xFFFF; LCDPCTL1 = 0x07FF; LCDPCTL2 = 0x00F0; // L0~L26 & L36~L39 pins selected LCDCTL0 = LCDSSEL_0 | LCDDIV_7; // flcd ref freq is xtclk // LCD Operation - Mode 3, internal 3.08v, charge pump 256Hz LCDVCTL = LCDCPEN | LCDREFEN | VLCD_6 | (LCDCPFSEL0 | LCDCPFSEL1 | LCDCPFSEL2 | LCDCPFSEL3); LCDMEMCTL |= LCDCLRM; // Clear LCD memory LCDCSSEL0 = 0x000F; // Configure COMs and SEGs LCDCSSEL1 = 0x0000; // L0, L1, L2, L3: COM pins LCDCSSEL2 = 0x0000; LCDM0 = 0x21; // L0 = COM0, L1 = COM1 LCDM1 = 0x84; // L2 = COM2, L3 = COM3 // Display "123456" LCDMEM[pos1] = digit[1]; LCDMEM[pos2] = digit[2]; LCDMEM[pos3] = digit[3]; LCDMEM[pos4] = digit[4]; LCDMEM[pos5] = digit[5]; LCDMEM[pos6] = digit[6]; LCDCTL0 |= LCD4MUX | LCDON; // Turn on LCD, 4-mux selected PMMCTL0_H = PMMPW_H; // Open PMM Registers for write PMMCTL0_L |= PMMREGOFF_L; // and set PMMREGOFF // __bis_SR_register(LPM3_bits | GIE); // Enter LPM3.5 // __no_operation(); // For debugger } void LCD_display_n(int number) { LCDMEMCTL |= LCDCLRM; // Clear LCD memory LCDCSSEL0 = 0x000F; // Configure COMs and SEGs LCDCSSEL1 = 0x0000; // L0, L1, L2, L3: COM pins LCDCSSEL2 = 0x0000; LCDM0 = 0x21; // L0 = COM0, L1 = COM1 LCDM1 = 0x84; // L2 = COM2, L3 = COM3 // Display "123456" int n = number / 100000; LCDMEM[pos1] = digit[n]; n = number - (100000*n); n = n/10000; LCDMEM[pos2] = digit[n]; n = number - (10000*n); n = n/1000; LCDMEM[pos3] = digit[n]; n = number - (1000*n); n = n/100; LCDMEM[pos4] = digit[n]; n = number - (100*n); n = n/10; LCDMEM[pos5] = digit[n]; n = number - (10*n); LCDMEM[pos6] = digit[n]; LCDCTL0 |= LCD4MUX | LCDON; // Turn on LCD, 4-mux selected }
  14. Like
    zeke reacted to monsonite in SIMPL - A Tiny Language for MSP430   
    Hi All
     
    Back in May 2013, I came across a piece of development work by Ward Cunningham (wiki inventor) for a tiny interpreted language "Txtzyme" that ran on Arduino - or virtually any other micro that was supported by a C compiler.
     
    (The name Txtzyme comes from text and enzyme -  an enzyme being a biological catalyst - or a substance that causes (chemical) change to occur faster).
     
    I was intrigued how under 100 lines of C code formed such a useful and extendable language - that I quickly had it running on an Arduino, and was making my own modifications and improvements.  I have since built on Ward's work and called my project SIMPL - Serial Interpreted Microcontroller Language.
     
    (Link to Ward's original work is here  https://github.com/WardCunningham/Txtzyme )
     
    Ward had created a "nano interpreter" in just a few lines of C code, which formed the heart of an interactive language for controlling hardware.
     
    Through just a dozen commands it would allow port manipulation,  flashing LEDs,  musical tone generation, PWM, printing to screen and sensing analogue signals. The language communicated through a uart port to the PC.
     
    Originally Txtzyme offered just these commands - see Ward Cunningham's Read Me:

    a-f      Select an I/O port
    h        help - a summary of commands
    i         input
    k        a loop counter - which decrements each time around the loop  see {}
    m       millisecond delay
    o       output
    p       print the value of variable x followed by carriage return/line feed
    s       sample an ADC channel
    u       microsecond delay
    x       a 16 bit integer variable
    {}     code between these braces is repeated as a loop
    _ _    characters between the underscores are printed to the terminal
     
    Txtzyme was small, entensible and portable - it will run on almost any microcontroller.  The Txtzyme scripts were very small, human readable and easy to send from one device to another.
     
    One early application was for the Arduino to be used as an I/O controller board attached to a Raspberry Pi.  The Pi would send a simple command via it's uart and the Arduino would perform an I/O function, sequence or whatever.
     
    Some months later, I decided to try Txtzyme with the MSP430, as I had got a LaunchPad and Energia had just appeared on my radar. 
    So I took the original Txtzyme Arduino  sketch, loaded into Energia - and behold it worked first time.  Txtzyme was a universal "lingua franca" that could be used on any micro.
     
    If you want to try  arecent version of SIMPL that runs on a LaunchPad MSP430G2553 - here is the Github Gist
     
    https://gist.github.com/anonymous/034dd41f108263d09803
     
    Since then I have ported it to  AVR Cortex M3, M4,  and several soft-core processors running on FPGAs.
     
    Currently my aim is to reduce the SIMPL Kernel to approximately 2kbytes - so that it can become a "Smart Bootloader"  - residing on the microcontroller in the bootloader area, and being immediately available as an interactive toolkit for exercising hardware and performing small applications.
     
    I have written extensively about it in my blog  - starting here  from May 2013
     
    http://sustburbia.blogspot.co.uk/2013/05/txtzyme-minimal-interpreter-and.html
     
    I have also just this week started a wiki - so that all the new information can reside in 1 place.
     
    https://simplex1.wiki.zoho.com/HomePage.html
     
     
    Please get in touch if you would like to know more about SIMPL and my project aims.  
     
     
     
     
    Ken 
     
    London
     
     
     
     
     
     
  15. Like
    zeke reacted to yyrkoon in Have you experienced a chilling effect?   
    There are several people here on this forum that I've learned from. Spirilis, oPossum, and Rickta are 3 especially that have made me think especially hard about what I'm doing in code. I would know nothing about any of the hardware I've worked with without their help. period.
     
    I've especially appreciated how oPossum has helped me the most recent. He did not write code for me, he waited for me to write code, and offered up a way for me to refactor that code. As well as offer insights as to what a high level "thing" could be doing in concept. Such as helping me identify sequence numbers from CANBUS output.
     
    In all though. There really is not much I can not figure out on my own, but it does certainly help to have others to discuss various situations / things with. It's pretty cool to be able to make a post saying "hey how does this work", and perhaps expand on that discussion some. At least I appreciate that sort of discussion.
  16. Like
    zeke reacted to yyrkoon in Have you experienced a chilling effect?   
    Write a book . . . that should make everyone happy, if it's a good one.
  17. Like
    zeke reacted to yyrkoon in Have you experienced a chilling effect?   
    Let me clarify on my post above.
     
    First, I would not necessarily feel that you're a morally reprehensive piece of garbage just because I think one thing, or another, that you do, is selfish. We're all selfish on some level, and have to be in order to take care of our own.
     
    So sharing single ideas based on hardware discussed here on the forums is all but a must. e.g. how to use an ADC, or PWM modules. By this I mean that individuals really have no right to hold back that information from others on this forum.That's common knowledge, or should be. Of course they're not obligated to share what they know, but why even bother being here if you're not willing to help, as well as learn.
     
    However, on the other hand. For example if someone were to write something from scratch, and perhaps unique. Let says that uses ADC, and PWM in a way to makes some sort of DC/DC converter( just an example ). I do not think it would be that persons responsibility to share that code with the community. In fact, quite the opposite. I thin if that person were to share that code with the public, that person should be required to make sure the public knows how to use the code properly( so as not to burn up hardware ).
     
    In my own case over the last IDK, maybe 6 months I've shared a bunch of code on single simple ideas. mostly because I was learning as I went, and figured what I learned might help give someone else some insight on the subject matter. At the same time, much of this code was put together into one large project that did multiple things to get towards an end goal. *That* code I did not share. Simply because I've shared enough code with the public that would allow a creative person to do the same thing I did. But I was not going to write this whole project for anyone other than myself to take advantage of.
  18. Like
    zeke reacted to yyrkoon in Have you experienced a chilling effect?   
    @@zeke
     
    I think you'd have you ask yourself one simple question. Were you born knowing everything ?
     
    Seriously. How did you learn to write software for this hardware? Was from this forum ? Another forum ? How did you learn to write code to begin with ? I think in this context, yes, you're being selfish. You can not expect to come to this forum, learn from others, and then expect exclusive rights for software you've learned from others. Passed this, programing concepts in general are hardly innovations in themselves. Meaning, if you can figure out how to write something in code, so can about 500,000 other individuals. Programming, on many levels, just is not that hard.
     
    In addition to the above. I'm not sure how you got "burnt" by another person, or how you *should* feel. But where I come from, our fathers have a saying too. "Water under to the bridge. . ." Meaning, maybe you unjustly got burned, but there is nothing you can do about that, now. Move on . . .
     
    EDIT:
     
    Also, if you feel honestly that you have created something special in code, and that it's worth something to you. FFS don't put  it on the internet . . . but again, that seems awfully selfish.
  19. Like
    zeke reacted to Fmilburn in Have you experienced a chilling effect?   
    I got involved with this community essentially knowing nothing about microcontrollers or C/C++ when I retired as an engineering manager with a mechanical background (in Calgary by the way - one of my  favorite places).  Microcontrollers were  just something that caught my interest after viewing a TED video on Arduino.  And on average, the quality of the projects and the help / discussion just seemed to be on a higher level on 43oh than with the Arduino crowd.
     
    For me, learning this stuff beyond the superficial on my own outside of a classroom setting and without colleagues is hard.  But it has been rewarding and a great experience.  And I have learned something from each of you who have posted above.  So, my thanks to you.
     
    This is just a hobby for me, and it is unlikely anyone developing a commercial product is going to gain much from my advice .  Having said that, I try to give as much as I take. And a good way to learn and hopefully help others has been to read the problems others are having and see if I can solve them.  For those who would like to continue getting that kind of help, here are some tips:
    Don't abuse the goodwill of 43oh members in the manner described above Search and make a real effort to solve it yourself first Post sufficient information for someone to help solve the problem but be as succinct as possible and don't post a 100 lines of code Use the thanks button when someone helps - really, how much effort does that take?  Somebody just spent personal time to help you for free. When your problem is solved, consider editing your first post and put [sOLVED] in the title, or at least follow up with a post that you finally got it to work and how.  The next person with that problem will thank you. My son-in-law has a masters in EE and is now a patent attorney.  I asked him a while back about the practicalities of protecting intellectual property for the small guy or hobbyist.  My interpretation of that conversation was that unless you have money and/or time it is difficult.  A shame, the result is that you must do something like Spirilis suggests and carefully consider/tier responses, help, and what is revealed. 
     
     I appreciate the help past and future, and enjoy hearing about the projects. But, I also understand the sentiments expressed above and don't want to see livelihoods threatened.
  20. Like
    zeke reacted to terjeio in Algorithm based stepper motor ramping for Tiva C   
    I have started the process of porting my CO2-laser driver from MSP430 to Tiva C and I am switching to an algorithm based approach for the stepper acceleration/deceleration. As part of testing I have (re)written an implementation of David Austins algorithm as documented here:
     
    http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time
     
    The test code may be of use for others so here it is.
     
    PA7: direction
    PF1: step pulse
     
    From what I can glean from my scope the interrupt handler executes in about 2us - so can be used for high pulse rates.
    // // Real-time stepper motor ramp control for TIVA C // // Based on article & code by David Austin // // Terje Io, 2016-03-08 // #include <stdint.h> #include <stdbool.h> #include "inc/hw_gpio.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "driverlib/sysctl.h" #include "driverlib/pin_map.h" #include "driverlib/gpio.h" #include "driverlib/pwm.h" #define STATE_IDLE 0 #define STATE_ACCEL 1 #define STATE_RUN 2 #define STATE_DECEL 3 #define STEPPULSE 50 #define PWMINT PWM_INT_CNT_AD | PWM_INT_CNT_BD typedef struct motor { uint8_t busy; // state machine state int16_t position; // absolute step number uint16_t move; // total steps to move uint16_t midpt; // midpoint of move bool odd; // true if odd number of steps int8_t pos_inc; // position increment uint16_t delay; // integer delay count uint16_t first_delay; // integer delay count uint16_t min_delay; // integer delay count uint16_t step_no; // progress of move uint16_t step_down; // start of down-ramp uint32_t c32; // 24.8 fixed point delay count int16_t denom; // 4.n+1 in ramp algo } motor; struct motor motor1; void pwm_1_2_int_handler (void); void motor_init (motor *motor) { motor->position = 0; motor->busy = STATE_IDLE; motor->pos_inc = 0; motor->first_delay = 30000; motor->min_delay = 1400; } bool motor_calc (motor *motor, int16_t pos_new) { if (pos_new < motor->position) { // get direction & #steps motor->move = motor->position - pos_new; motor->pos_inc = -1; } else if (pos_new != motor->position) { motor->move = pos_new - motor->position; motor->pos_inc = 1; } else return false; // already there motor->odd = motor->move & 0x0001; motor->midpt = (motor->move - (motor->odd ? 1 : 0)) >> 1; motor->step_no = 0; // step counter motor->delay = motor->first_delay; motor->c32 = ((uint32_t)motor->delay) << 8; // keep delay in 24.8 fixed-point format for ramp calcs motor->denom = 1; // 4.n + 1, n = 0 return motor->busy = motor->move == 1 ? STATE_DECEL : STATE_ACCEL; } void motor1_run (int16_t pos_new) { if(motor_calc(&motor1, pos_new)) { GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, motor1.pos_inc > 0 ? GPIO_PIN_7 : 0); PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, motor1.delay); PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5, STEPPULSE); PWMGenEnable(PWM1_BASE, PWM_GEN_2); } } void mpu_init (void) { SysCtlPWMClockSet(SYSCTL_PWMDIV_8); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); SysCtlDelay(26); // wait for modules to start GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7); GPIOPadConfigSet(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD); // PWMClockSet(PWM1_BASE, PWM_SYSCLK_DIV_64); GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_1); GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_STRENGTH_12MA, GPIO_PIN_TYPE_STD); GPIOPinConfigure(GPIO_PF1_M1PWM5); PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_GEN_SYNC_LOCAL); PWMOutputState(PWM1_BASE, PWM_OUT_5_BIT, true); PWMGenIntRegister(PWM1_BASE, PWM_GEN_2, pwm_1_2_int_handler); PWMGenIntClear(PWM1_BASE, PWM_GEN_2, PWMINT); PWMGenIntTrigEnable(PWM1_BASE, PWM_GEN_2, PWMINT); PWMIntEnable(PWM1_BASE, PWM_INT_GEN_2); } void main(void) { SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); motor_init(&motor1); mpu_init(); while (true) { // repeat 5 revs forward & back motor1_run(8000); // 1.8 deg/step and 8 microsteps while (motor1.busy); motor1_run(0); while (motor1.busy); } } void pwm_1_2_int_handler (void) { PWMGenIntClear(PWM1_BASE, PWM_GEN_2, PWMINT); motor1.position += motor1.pos_inc; motor1.step_no++; switch (motor1.busy) { case STATE_ACCEL: if (motor1.step_no == motor1.midpt) { motor1.busy = motor1.odd ? STATE_RUN : STATE_DECEL; motor1.step_down = motor1.step_no + 1; motor1.denom -= 2; } else { motor1.denom += 4; motor1.c32 -= (motor1.c32 << 1) / motor1.denom; // ramp algorithm motor1.delay = (motor1.c32 + 128) >> 8; // round 24.8 format -> int16 if (motor1.delay <= motor1.min_delay) { // go to constant speed? motor1.denom -= 6; motor1.busy = STATE_RUN; motor1.step_down = motor1.move - motor1.step_no; motor1.delay = motor1.min_delay; } PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, motor1.delay); PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5, STEPPULSE); } break; case STATE_RUN: if (motor1.step_no == motor1.step_down) motor1.busy = STATE_DECEL; break; case STATE_DECEL: if (motor1.denom < 2) // done? motor1.busy = STATE_IDLE; else { motor1.c32 += (motor1.c32 << 1) / motor1.denom; // ramp algorithm motor1.delay = (motor1.c32 - 128) >> 8; // round 24.8 format -> int16 motor1.denom -= 4; PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, motor1.delay); PWMPulseWidthSet(PWM1_BASE, PWM_OUT_5, STEPPULSE); } break; } // switch (busy) if(!motor1.busy) PWMGenDisable(PWM1_BASE, PWM_GEN_2); }
  21. Like
    zeke reacted to spirilis in Have you experienced a chilling effect?   
    All that said, I do wonder if you have "tiers" of information you could feel comfortable giving out, or if it's all just one sacred space for you... I think "tiering" the level of advice and knowledge is key to managing a public footprint that's open enough to keep others excited about what you do, but having a reasonably firm line protecting what you consider pay-worthy in terms of time commitment.
     
    Some of us are in different situations where everything we do in this realm is for hobby, but some aren't.
  22. Like
    zeke reacted to Rickta59 in Have you experienced a chilling effect?   
    For msp430 topics, there are users in #43oh channel on freenode.net. 
     
    http://webchat.freenode.net/?channels=43oh&nick=guest_from_post ... replace the nick with a better one if you like
  23. Like
    zeke reacted to L.R.A in Have you experienced a chilling effect?   
    I feel the exact same Zeke, I got some projects I feel like not sharing as much info as before, or no info at all.

    I get lots of times people asking me to help with a project. Students I usually don't have much problem in helping out just enough but many times it seems to be for products and well, why should I help you? You're getting paid, I'm not - if it was a friend then well I can help a bit

    I feel a bit that with the info on my website. I shared tutorials and all - I must have gotten like 1 thank you in 2 years.
    Once I took the site off - there was the possibility of teaching for payment how to use the TM4C so I didn't want to gave my tutorials out there - I needed to think. Well, then people we're quick to insult me, call my website useless (it was with just projects, with code and tutorials on them mind you) because I took the info off. That's why now I mostly make stuff only for people I know, at least they can buy me a drink or at least say thanks. I even got some to help me out making them.

     
  24. Like
    zeke reacted to Rickta59 in Have you experienced a chilling effect?   
    I have some of the same feelings zeke.
     
     
    What I've done is to only dole out information in real time using IRC.  This allows me to gauge who is looking for the information and why.  If it is for commercial use I just ignore them. If it is a lazy student, I especially ignore them.  If it someone like me, just looking to find out the information for their own benefit, I share freely.
     
    -rick
  25. Like
    zeke reacted to spirilis in Have you experienced a chilling effect?   
    Sounds like you're getting old ;-)
    *ducks*
×
×
  • Create New...