Shop OBEX P1 Docs P2 Docs Learn Events
C3 and XMMC — Parallax Forums

C3 and XMMC

RsadeikaRsadeika Posts: 3,837
edited 2013-12-23 04:26 in Propeller 1
I started a new project using the C3, now I want it too work just like the program that I have for the DNARTC board. For the C3 I am using the softRTC and I am using the XMMC mode. On the DNARTC board I was using the CMM mode, and I was starting COGs to do the background tasks, to run sht11 and my senselog. So, the big question is, how do I accomplish the same thing on the C3 board, using XMMC mode? I know threads are available, but I doubt that it could be set up too run like a COG, doing its own thing. Anybody have any ideas or suggestions?

Ray

Comments

  • RsadeikaRsadeika Posts: 3,837
    edited 2013-12-21 06:40
    I was looking at some of the examples that are available, and noticed that the cogc toggle code might be a direction to go. The program below, I wanted to get down to the basics of doing a cogc program, the program is almost working the way I want it. The problem is in the .cogc file, I cannot figure out how too pause the blink. I tried the different forms of waitcnt, but none of them seem to be working.

    This program, at this stage, is running as expected in LMM, and XMMC modes, so that is a good sign.

    Ray
    /**
     * blink.c
     * December 21, 2013
     */
    #include <stdio.h>
    #include <unistd.h>
    #include <propeller.h>
    #include "blink.h"
    
    struct {
      volatile struct blink_mailbox m;
    } par;
    
    void start(volatile void *parptr)
    {
      extern unsigned int _load_start_blink_cog[];
    #if defined(__PROPELLER_XMM__) || defined(__PROPELLER_XMMC__)
      load_cog_driver_xmm(_load_start_blink_cog, 496, (uint32_t*)parptr);
    #else
      cognew(_load_start_blink_cog, parptr);
    #endif
    }
    
    #define MIN_GAP 400000
    
    int main(int argc, char* argv[])
    {
      sleep(1);
      printf("Hello, World!\n");
    
      start(&par.m);
      return 0;
    }
    
    
    /* blink.h
     * December 21, 2013
     */
    
    struct blink_mailbox {
    
    };
    
    /* blink.cogc
     * December 21, 2013
     */
    
    #include <propeller.h>
    #include "blink.h"
    
    static _COGMEM unsigned int nextcnt;
    static _COGMEM unsigned int pin = 0x800000;
    static _COGMEM unsigned int waitdelay;
    
    _NATIVE
    void main(struct blink_mailbox *m)
    {
      _DIRA = pin;
      //waitcnt(CNT + CLKFREQ);
      //waitcnt2(_CNT, _clkfreq);
      while(1)
      {
        _OUTA ^= pin;
        //waitcnt2(_CNT, _clkfreq);
      }
    }
    
  • mindrobotsmindrobots Posts: 6,506
    edited 2013-12-21 06:47
    Ray,

    Other than defining it, I don't see where you actually give waitdelay any value. Don't you need to provide an actual time to wait somehow? It's probably working just as you indicate but the delay is 0 plus execution time of the code in the loop.
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-12-21 07:13
    Yes, the LED, at this time, is toggling at the clock rate. I put in the waitdelay, but I am not using it because, in the toggle cogc example, it looks relatively complicated, so I am trying to figure out away of using something like waitMS(1000) command. I would like to make the pause work in the simplest manner as possible, in a cogc form.

    The other thing that I noticed is that not everything will work in a cogc form, I tried using sleep(1), the cogc did not except that, for whatever reason, or at least the compiler did not like that. It also did not like waitcnt(CNT + CLKFREQ), this is standard stuff in the xxx.c program.

    Ray
  • photomankcphotomankc Posts: 943
    edited 2013-12-21 09:31
    Unless my eyes are broken.....


    waitcnt(a) is nothing more than "wait until the system timer reaches this number". The normal way to accomplish a 1ms wait would be:
    int delay = CLKFREQ/1000;
    waitcnt(CNT + delay);
    

    So you establish that you want to wait 80_000_000/1_000 ticks or 80_000 ticks. Lets say system timer is currently at 10_000 ticks.
    Then you tell waitcnt() that you want to wait until timer is at 10_000+80_000 or 90_000 ticks.


    I'm not familiar with waitcnt2() but waitcnt() is certainly able to fill the need to set a blink rate. You have the right syntax right in there with this earlier line which would produce a 1000ms blink rate:
      //waitcnt(CNT + CLKFREQ);
    

    This would give 1ms blink:
      waitcnt(CNT +(CLKFREQ/1000));
    

    This would give a 100ms blink:
      waitcnt(CNT +(CLKFREQ/10));
    
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-12-21 12:45
    I manipulated the code and I got it to blink at about a second, but, I do not know why it is doing it. Before I show any code I need to know what this means and/or what it is doing:
    static _COGMEM unsigned int pin = 0x800000; //P23
    _OUTA ^= pin;
    
    I know that in PASM you use 'OUTA[1] = 1' to set P1 too an output state, but what the heck is it doing in C?

    Ray
  • photomankcphotomankc Posts: 943
    edited 2013-12-21 22:09
    Rsadeika wrote: »
    I manipulated the code and I got it to blink at about a second, but, I do not know why it is doing it. Before I show any code I need to know what this means and/or what it is doing:
    static _COGMEM unsigned int pin = 0x800000; //P23
    _OUTA ^= pin;
    
    I know that in PASM you use 'OUTA[1] = 1' to set P1 too an output state, but what the heck is it doing in C?

    Ray

    Exclusive OR. It acts to toggle the pin. If both values are 1 then the result is 0 and that result is stored back into _OUTA. If one bit is 0 and the other bit is 1 then it acts as a normal OR and the result is 1 and is stored back into _OUTA.
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-12-22 04:48
    In the program below I wanted to see if in fact you can pass some values back and forth between the COGs, Well in this case I can get the value that is in the blink.cogc, and print it from the main COG. This is a very tedious way of trying to find out what the limitations of a cogc function are. I guess not too many people are interested in this functionality. But, I will share, until of course I get ...

    As for the actual blink of the LED, I was aware that '^=' is a toggle functionality, but what if you want set 'OUTA' so that it actually sets the pin state too a '1' or '0'? Like I mentioned earlier, in PASM 'OUTA[23] = 1' is what you would do, but in the cogc function this does not compile. Could not find the correct form to make this work in a cogc function.

    Ray

    /**
     * blink.c
     * December 21, 2013
     */
    #include <stdio.h>
    #include <unistd.h>
    #include <propeller.h>
    #include "blink.h"
    
    struct {
      unsigned stack[STACK_SIZE];
      volatile struct blink_mailbox m;
    } par;
    
    void start(volatile void *parptr)
    {
      extern unsigned int _load_start_blink_cog[];
    #if defined(__PROPELLER_XMM__) || defined(__PROPELLER_XMMC__)
      load_cog_driver_xmm(_load_start_blink_cog, 496, (uint32_t*)parptr);
    #else
      cognew(_load_start_blink_cog, parptr);
    #endif
    }
    
    volatile int blink_cog_count;
    
    #define MIN_GAP 400000
    
    int main(int argc, char* argv[])
    {
      sleep(1);
      printf("Hello, World!\n");
    
    
    /* Not sure what this is doing?*/
      par.m.wait_time = _clkfreq;  // need this.
      start(&par.m);  // This starts the blink.cogc.
    /* This seems to control the clock rate of blink.cogc. */
      par.m.wait_time = _clkfreq;  // need this.
      while(1)
      {
        sleep(1);
        printf("Count = %d\n",blink_cog_count);
      }
      return 0;
    }
    
    /* blink.h
     * December 21, 2013
     */
    
    struct blink_mailbox {
      unsigned int wait_time;
    };
    
    #define STACK_SIZE 16
    
    
    /* blink.cogc
     * December 21, 2013
     */
    
    #include <propeller.h>
    #include "blink.h"
    
    static _COGMEM unsigned int nextcnt;
    static _COGMEM unsigned int pin = 0x800000; //P23
    static _COGMEM unsigned int waitdelay;
    
    /* This variable used between the cogs. */
    extern int blink_cog_count;
    
    _NATIVE
    
    void main(struct blink_mailbox *m)
    {
     
    //  _DIRA = pin;
      nextcnt = _CNT + m->wait_time;
      while(1)
      {
    //    waitdelay = m->wait_time; // This needed for pin toogle.
    //    _OUTA ^= pin;             // Toggle the pin (P23)
    /* Without this the value of 15 does not appear in the main cog.
       This seems to make the while() functional? */
        nextcnt = waitcnt2(nextcnt, waitdelay);
    /* This variable is available to the main cog.*/ 
        blink_cog_count = 15;
      }
    }
    
    
  • photomankcphotomankc Posts: 943
    edited 2013-12-22 07:20
    You use a mask since C has not bit access notation like spin. The mask has only the bit / bits you want to effect set. To set those bits in OUTA you OR the mask against OUTA and then store the result in OUTA. This adds your 1s into the value while preserving all existing 1s. To clear them you AND the *inverse* of your mask against OUTA and store the result in OUTA.
  • jazzedjazzed Posts: 11,803
    edited 2013-12-22 07:38
    Ray,

    Your blink_cog_count variable needs to be part of the mailbox, otherwise it shouldn't work.
    struct blink_mailbox {
      unsigned int wait_time;
      int blink_cog_count;
    };
    
    Once you do that, use it in the cog main as;

    m->blink_count_cog = 15;

    The printf will have:

    printf("Count = %d\n",par.m.blink_cog_count);


    Set outa to pin mask:

    OUTA |= pin; // as photomankc said OR the MASK


    Clear outa to pin mask:

    OUTA &= ~pin; // as photomankc said AND the inverse MASK ... ~ in C means invert
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-12-22 07:42
    It looks like I will have to find the functions that I wrote for adding the commands, high(), low(), and probably a version of pause(), unless of course you happen to have some handy.

    Ray
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-12-23 04:26
    For this version I added another cogc to the mix, a blinker, and the other cogc just prints a particular value. In the blink2.cogc, I still can not figure out why a waitcnt() is not an acceptable function, in the cogc function. This waitcnt() function is the basis for creating a viable pause() function, and I do not know how to apply waitcnt2() too use instead of a waitcnt().

    From the very small amount of information that is available, I get the impression that a cogc COG is a normal sized COG, meaning just because you are using XMMC mode, does not mean that the cogc grows beyond the ~396 byte size. Not sure how this uses the HUB memory though, does it just share the 32k?

    I tried implementing the sht11.c into one of the cogc functions, the program did not like that at all. It seems that the sht11.c relies heavily on the simpletools library and the addition of a cogc function does not like simpletools.h. More experimentation is being done, I just do not know where this is heading.

    Ray

    /**
     * blink.c
     * December 21, 2013
     */
    #include <stdio.h>
    #include <unistd.h>
    #include <propeller.h>
    #include "blink.h"
    
    
    struct {
      unsigned stack[STACK_SIZE];
      volatile struct blink_mailbox m;
    } par;
    
    void start(volatile void *parptr)
    {
      extern unsigned int _load_start_blink_cog[];
      extern unsigned int _load_start_blink2_cog[];
    #if defined(__PROPELLER_XMM__) || defined(__PROPELLER_XMMC__)
      load_cog_driver_xmm(_load_start_blink_cog, 496, (uint32_t*)parptr);
      load_cog_driver_xmm(_load_start_blink2_cog, 496, (uint32_t*)parptr);  
    #else
      cognew(_load_start_blink_cog, parptr);
      cognew(_load_start_blink2_cog, parptr);
    #endif
    }
    
    volatile int blink_cog_count;
    volatile int blink2_cog_count;
    
    
    #define MIN_GAP 400000
    
    int main(int argc, char* argv[])
    {
      sleep(1);
      printf("Hello, World!\n");
    
    
    /* Not sure what this is doing?*/
      par.m.wait_time = _clkfreq;  // need this.
      start(&par.m);  // This starts the blink.cogc.
    /* This seems to control the clock rate of blink.cogc. */
      par.m.wait_time = _clkfreq;  // need this.
      while(1)
      {
        sleep(1);
        printf("Count = %d\n",blink_cog_count);
    //    printf("Count = %d\n",blink2_cog_count);
      }
      return 0;
    }
    
    
    /* blink.h
     * December 21, 2013
     */
    
    struct blink_mailbox {
      unsigned int wait_time;
    };
    
    #define STACK_SIZE 16
    
    
    /* blink.cogc
     * December 21, 2013
     */
    
    #include <propeller.h>
    #include "blink.h"
    
    
    static _COGMEM unsigned int nextcnt;
    static _COGMEM unsigned int pin = 0x800000; //P23
    static _COGMEM unsigned int waitdelay;
    
    /* This variable used between the cogs. */
    extern int blink_cog_count;
    
    _NATIVE
    
    void main(struct blink_mailbox *m)
    {
    
    
     
    //  _DIRA = pin;
      nextcnt = _CNT + m->wait_time;
      while(1)
      {
    //    waitdelay = m->wait_time; // This needed for pin toogle.
    //    _OUTA ^= pin;             // Toggle the pin (P23)
    /* Without this the value of 15 does not appear in the main cog.
       This seems to make the while() functional? */
        nextcnt = waitcnt2(nextcnt, waitdelay);
    /* This variable is available to the main cog.*/ 
        blink_cog_count = 15;
      }
    }
    
    
    /*
    * blink2.coc
    * December 21, 2013
    */
    
    #include <propeller.h>
    #include "blink.h"
    
    static _COGMEM unsigned int nextcnt;
    static _COGMEM unsigned int waitdelay;
    static _COGMEM unsigned int pin = 0x400000; //P22
    
    extern int blink2_cog_count;
    
    _NATIVE
    
    
    
    
    void high(int pin);
    void low(int pin);
    
    void main(struct blink_mailbox *m)
    {
     
    //  _DIRA = pin;
      nextcnt = _CNT + m->wait_time;
      while(1)
      {
        waitdelay = m->wait_time; // This needed for pin toogle.
    //    _OUTA ^= pin;             // Toggle the pin (P23)
        high(22);
    
    /* Without this the value of 15 does not appear in the main cog.
       This seems to make the while() functional? */
        nextcnt = waitcnt2(nextcnt, waitdelay);
    
        low(22);
    
        nextcnt = waitcnt2(nextcnt, waitdelay);
    
    /* This variable is available to the main cog.*/ 
    //    blink2_cog_count = 20;
      }
    }
    
    void high(int pin)                            // high function definition
    {
      int mask = 1 << pin;                        // Set up mask
      OUTA |= mask;                               // Bitwise OR w/ OUTA & DIRA
      DIRA |= mask;
    }
    void low(int pin)                             // low function definition
    {
      int mask = 1 << pin;                        // Set up mask
      OUTA &= ~mask;                              // Pin output state to low
      DIRA |= mask;                               // Pin direction to output
    }
    
    
Sign In or Register to comment.