Shop OBEX P1 Docs P2 Docs Learn Events
New to C? ... check in here — Parallax Forums

New to C? ... check in here

UnsoundcodeUnsoundcode Posts: 1,532
edited 2011-11-10 18:43 in Propeller 1
Hi , I’m guessing there will be a lot of new Propeller users and existing forum members wanting to use or at least try the C programming environment. I thought it would be a good idea to present a C primer to people completely new to C or rusty intermediates (I would say I am somewhere between). It’s my intention and hope that this thread be completely devoted to the PEKitLabs Fundamentals and here new users can learn and teach from and to each other. I encourage people to post their own conversions in C from the labs and I would like to see the more advanced users give assistance and pointers (without providing the whole solution). If enough examples get posted, and are well commented, we can perhaps select a few of the best for a “sticky”. This should keep us going until they re-write the book.

I am attaching a primer for absolute beginners and intend to do more soon. The primer is a conversion of one of the labs first Spin files. Feel free to be critical I can probably correct any mistakes.

Jeff T.

UPDATE
Uploaded a txt version and jpeg for non MS Word users. Note the header should be corrected to be #include <propeller.h> and in the text file Int main should read int main.

UPDATE #2
Uploaded C Primer Part 2
«1

Comments

  • RossHRossH Posts: 5,514
    edited 2011-11-05 18:41
    Hi Jeff.

    Good idea. A couple of little things:

    Page 1 you have a typo - Int main() - i.e. capital "I". C is case sensitive, so "Int" is not the same as "int"
    Page 2 should probably say #include <Propeller.h>. The <file_name> notation means a system header file, while "file_name" means one of your own project header files. In this case I believe it should be a system header file. If either one works then it could indicate you have either a duplicate file, or a problem with your inlcude file paths - either one of which can cause you much grief down the track.

    Ross.
  • jazzedjazzed Posts: 11,803
    edited 2011-11-05 19:35
    Jeff, that looks awesome :)

    Ross had helpful comments: I guess Word was trying to help auto-correct the first letter of a sentence. File propeller.h can be found in the system include path, and it should be all lower case: #include <propeller.h>. The latest propeller.h has been updated with many "propellery" #define macros, but it is missing cogid (fix queued for the next snapshot).
  • RonPRonP Posts: 384
    edited 2011-11-05 21:26
    Hey Jeff and All,

    Checking in, can't wait to take a look at your primer. I just reloaded my laptop with Vista today and I am going to dual boot fedora 15 also in the middle of updating fedora 15 now and don't have an Office Program installed to read your .doc just yet, but soon. I mentioned in another post that I wasn't much of a "command line guy" well I am not much of a programmer either but I am going to jump in head first and see what happens(i'll wear a helmet).

    -Ron
  • Kevin WoodKevin Wood Posts: 1,266
    edited 2011-11-05 21:53
    > I just reloaded my laptop with Vista today and I am going to dual boot fedora 15 also in the middle of updating fedora 15 now and don't have an Office Program installed to read your .doc just yet, but soon.

    OpenOffice should be in the Fedora repos, and you can download LibreOffice (successor to OpenOffice) form their site.
  • RonPRonP Posts: 384
    edited 2011-11-05 22:53
    @Kevin,

    Just finished updating and tweaking fedora going to take a look at the .doc now. Then download propgcc and see how it works with fedora. I never did get propgcc to work with Ubuntu but I had it going in Vista. It was time for me to wipe out Vista and reload it anyway (once a year) so I thought I would give fedora try, I ended up with LibreOffice.

    Thanks Ron
  • potatoheadpotatohead Posts: 10,261
    edited 2011-11-05 23:25
    This is a pretty great primer.
  • Kevin WoodKevin Wood Posts: 1,266
    edited 2011-11-06 01:10
    Ron, you shouldn't have any problems with Fedora 15. It runs here on Scientific Linux 6.0, which is derived from Fedora 12 & 13.
  • RonPRonP Posts: 384
    edited 2011-11-06 02:24
    Kevin and All,

    I am having problems with he FTDI Driver or the '/dev/ttyUSB0 port'. Not sure what's wrong. I had a USB hub hooked up so I unplugged it with nothing but the Propeller plugged in. Tried BST and it cant find the Propeller either. BST worked on my Unbuntu Box with the same USB hub so I don't know. I didn't think I would have problems with fedora either I am going to have to figure this out I am kinda fond of this Gnome 3 desktop. The code compiled fine just can't load it. Its getting late I try and figure it out tomorrow. See below maybe you'll have some ideas. I tried to restart between unplugging the USB HUB also.
    [ron@fedora myC]$ propeller-load PushbuttonLEDTest -r
    Invalid file handle for serial port '/dev/ttyUSB0' [B]I keep getting this line.[/B]
    Error 'Permission denied'
    error: opening serial port
    [ron@fedora myC]$ lsusb [B]I did this lsusb command to see if the FTDI was there and it appears to be so I don't know.[/B]
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
    Bus 003 Device 010: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
    Bus 002 Device 013: ID 05e3:0608 Genesys Logic, Inc. USB-2.0 4-Port HUB
    Bus 002 Device 003: ID 04f2:b008 Chicony Electronics Co., Ltd USB 2.0 Camera
    Bus 002 Device 014: ID 046d:c52b Logitech, Inc. Unifying Receiver
    Bus 002 Device 015: ID 046d:c517 Logitech, Inc. LX710 Cordless Desktop Laser
    [ron@fedora myC]$ 
    

    Its probably something silly I am overlooking. :smile:

    Learning a lot Ron
  • ersmithersmith Posts: 6,100
    edited 2011-11-06 03:09
    RonP wrote: »
    I am having problems with he FTDI Driver or the '/dev/ttyUSB0 port'. Not sure what's wrong. I had a USB hub hooked up so I unplugged it with nothing but the Propeller plugged in. Tried BST and it cant find the Propeller either. BST worked on my Unbuntu Box with the same USB hub so I don't know. I didn't think I would have problems with fedora either I am going to have to figure this out I am kinda fond of this Gnome 3 desktop. The code compiled fine just can't load it. Its getting late I try and figure it out tomorrow. See below maybe you'll have some ideas. I tried to restart between unplugging the USB HUB also.
    [ron@fedora myC]$ propeller-load PushbuttonLEDTest -r
    Invalid file handle for serial port '/dev/ttyUSB0' [B]I keep getting this line.[/B]
    Error 'Permission denied'
    error: opening serial port
    
    The "permission denied" probably means that the permissions on /dev/ttyUSB0 aren't letting you in. Try
    ls -l /dev/ttyUSB*
    
    and look at the owner, group, and read/write permissions. On Ubuntu access is restricted to the "root" and "dialout" groups, but all console users are placed in "dialout" by default. On Fedora perhaps you have to explicitly add users to that group. If all else fails, you can (as root) do
    chmod 0666 /dev/ttyUSB0
    
    to make sure everyone can read/write the port.

    Eric
  • Kevin WoodKevin Wood Posts: 1,266
    edited 2011-11-06 03:54
    I think that you do need to manually add yourself to the dialout group with Fedora. The easiest way to check if it's a permission issue is to use sudo... sudo propeller-load -r yourfilename.

    Note on sudo... you can configure the sudoers file to not ask you for a password, which is my suggestion. Add yourself to the wheel group, and look for the no password line in the sudoers file. To edit the file, you can run visudo. This is a bit different than the way Ubuntu handles things, but IMO, it works more smoothly.
  • jazzedjazzed Posts: 11,803
    edited 2011-11-06 08:52
    The Users and Groups GUI in Linux can be used to add dialout to your user groups. It may be necessary to add sudo to the groups also. For temporary serial port testing it's probably better just to log in as root with "su" . Don't stay logged in as root though - doing so may leave you open to an attack.

    In Debian Users and Groups is in System->Administration. Not sure where it is in Fedora. I've used Fedora 13 with propeller-gcc although the compier generated version warnings - __red__ will be building .rpm packages for us later.
  • RonPRonP Posts: 384
    edited 2011-11-06 12:27
    Hi All,

    I checked if it was a permission issue per Kevin's suggestion (sudo propeller-load -r yourfilename) and it was for a quick fix I did as ersmith suggested below I will look at setting permissions in User Groups when I can find them in fedora. jazzed its working in fedora 15 now.
    chmod 0666 /dev/ttyUSB0
    

    @Unsoundcode sorry should have started a new thread for this I guess. Nice Primer I like you explanation about the bitmasks thanks for your efforts. Just what I needed to get going.

    Thanks All

    Ron
  • TorTor Posts: 2,010
    edited 2011-11-06 13:34
    @RonP:
    You should definitely try the add-to-group thing, not sure how it's done in Fedora. On Ubuntu and Debian it's as simple as opening a terminal, then 'sudo adduser your-name dialout', then log completely out, and in again. There are presumably some GUI admin tools to do that as well, but they change all the time so I don't bother trying to learn them or find them.
    On Fedora and other RedHat-derived distros there's no 'adduser' that works that way, for some reason. But for any distro (including Ubuntu and Debian, and any Unix anywhere) you can also simply log in as root, then edit /etc/group and add yourself to the dialout group. Although, on some distros, it's not 'dialout' but 'uucp'. It's whatever you see when you do 'ls -l /dev/ttyUSB0'. That's what the tools do: They edit that line in /etc/group

    The reason it's better to add yourself to the correct group than to change the access with 'chmod' is that nowadays the /dev/ filesystem is dynamic, and /dev/ttyUSB0 is created and deleted automatically as you plug and unplug your propeller. That means that the 'chmod' method doesn't stick: You'll have to do it again and again whenever you unplug and plug in the propeller. Adding yourself to the correct group is permanent.

    -Tor
  • RonPRonP Posts: 384
    edited 2011-11-06 16:10
    @Tor,

    Yes you are correct the "chmod' method doesn't stick" l am looking into the whole 'user group' thing now. Its different in Fedora that's for sure.

    Thanks Ron

    EDIT:

    All is fine now in Gnome 3 the 'User Manger GUI' isn't readily available but if you search 'user group' an icon will show up for it, then changes can be made. I added my self to the 'dialout' group in the GUI, a restart was needed in my case.

    Thanks again All,

    Ron
  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2011-11-08 11:50
    Moving forward with the PEK Labs I added Primer part 2 to the original post. I encountered a hurdle at the very first example of Chapter 4: I/O and Timing Basics Lab. The first example uses the spin instructions Dira[4] := 1 and Outa[4] := 1 to set P4 high and light an LED. These instructions are not available to us in propgcc so it means creating them ourselves, this is what makes coding so interesting.

    This part of the primer expands on the use of the #define directive to create the above instructions, additional material on the use of masks and lastly to write your own header file.

    The conversion at the end, LedOnP4.spin to LedOnP4.c is the beginning of the journey into programming the Propeller, it is so basic yet so rewarding.

    As a last note in this post if anyone has a better solution to the functions I used in this example please post them here.

    Jeff T.
  • RonPRonP Posts: 384
    edited 2011-11-08 14:43
    @Jeff

    Last night I was trying to figure out how to make a header file for the IO pin's. Your Primer couldn't have come at a better time for me. I was getting discouraged and was just about to give up, and go back to learning more SPIN witch is probably what I should be doing with my free time. But this is FUN. Everything in the Primer worked for me.

    Appreciate the time your taking to make these Primers. :smile:

    Ron
  • ersmithersmith Posts: 6,100
    edited 2011-11-08 16:28
    The most straightforward way to do Dira[4] := 1 and Outa[4] := 1 in propgcc is:
    #include <propeller.h>
    
    _DIRA |= (1<<4);
    _OUTA |= (1<<4);
    

    Eric
  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2011-11-08 17:01
    Thank you Eric that looks much better, I will adjust the docs to match, I appreciate the time you took to look things over.

    Ron I'm glad your enjoying it, I am. The header was certainly introduced at a convenient time, to implement Erics suggestion involves modifying just the one file. I plan on one more primer discussing variables, the for loop and a simple function. If you think you will take to C then you might consider a good book for reference, and how much does it cost for the expert advice we can get here...Priceless!!

    regards
    Jeff T.

    EDIT. I wondered if there might also be a better way to express Outa[4]:=0
  • jazzedjazzed Posts: 11,803
    edited 2011-11-08 18:22
    EDIT. I wondered if there might also be a better way to express Outa[4]:=0
    OUTA &= ~(1<<4)
    (or _OUTA &= ~(1<<4) if propeller.h is not included.)

    The tutorial is wonderful.
  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2011-11-09 17:19
    Thanks to Eric and Steve our header definitions are looking really good now, the header really makes the Spin to C conversions of the PEK Labs earlier examples a breeze to convert. I would say what we have will get us through 90% of Chapter 4. Things get really interesting in Chapter 5 when we get into methods and cogs, not quite ready on my end yet but there will be info posted here very soon. In the mean time here is a screen shot of the updated header file "myheader.h"

    Jeff T.

    EDIT: Kevin Wood suggested several good programs for typing and editing code files and headers, I chose Programmers Notepad which is a free download, personally I like it very much.
    878 x 205 - 29K
  • jazzedjazzed Posts: 11,803
    edited 2011-11-09 18:46
    You know, I was thinking about HIGH, LOW, and IN PBASIC style the other day.
    I'm sure folks around here would be comfortable with that too.

    Sounds like a +1 for that Programmers Notepad. I'll have to try it.
    Looks good in the website. Maybe a tutorial for that will appear (Kevin?).
  • Martin HodgeMartin Hodge Posts: 1,246
    edited 2011-11-09 19:36
    NoteTab or NoteTab Pro
  • UnsoundcodeUnsoundcode Posts: 1,532
    edited 2011-11-10 05:18
    I was thinking about HIGH, LOW, and IN PBASIC style the other day

    That's one of the first obstacles that you come up against in the PEK Labs, not only are we (the beginners amongst us) learning the features of the Propeller we have to learn to translate Spin into C. One of the aims of the header file creation is to act as an equalizer between learning C and learning the Prop, it allows us to progress with the labs and produce C code that is almost identical to Spin code.

    I hope that people with more imagination than I have will give their own names to "myheader.h" and the function macros it contains, the actual content of the header I do like though.The next addition will be not(pin); the equivalent of !OUTA[pin] and it will be used in a function that takes parameters, we will really be cooking with gas then.

    Jeff T.
  • ersmithersmith Posts: 6,100
    edited 2011-11-10 05:56
    The next addition will be not(pin); the equivalent of !OUTA[pin] and it will be used in a function that takes parameters, we will really be cooking with gas then.

    I think the simplest definition of this would be:
    #define not(pin) _OUTA ^= (1<<pin)
    

    (This uses C's exclusive or operator to invert bit "pin" in OUTA.)

    Eric
  • jazzedjazzed Posts: 11,803
    edited 2011-11-10 07:26
    Jeff, if the community can settle on simple macro naming like HIGH, LOW, NOT, IN, etc... we could put them in propeller.h or add a p8x32a.h header file that defines them. Later when propeller 2 is available we can make HIGHx, etc... variants for ports.
  • mindrobotsmindrobots Posts: 6,506
    edited 2011-11-10 08:50
    Mine are a little more verbose (which is strange since I can't type) but they are less ambiguous. I think they read rather nicely and leave primitive words like HIGH, LOW, NOT for more general definition.

    The only thing I'd like to do additionally is be able to set multiple pins through the #define
    #include <propeller.h>
    #define set_input_pin(pin) _DIRA &= ~(1<<pin)  // set selected 'pin' bit in DIRA to 0 (input)
    #define set_output_pin(pin) _DIRA |= (1<<pin)  // set selected 'pin' bit in DIRA to 1 (output)
    
    #define set_low_pin(pin) _OUTA &= ~(1<<pin)   // set selected 'pin' bit as LOW output 
    #define set_high_pin(pin) _OUTA |= (1<<pin)     // set 'pin' bit as HIGH output
    #define invert_pin(pin) _OUTA ^= (1<<pin)      // invert the 'pin' bit in OUTA
    
    #define read_pin(pin) (_INA & (1<<pin)) >> pin  // and the 'pin' bit with INA and then shift down to 1 or 0
    
    int main()
    {
        set_input_pin(25);
        set_output_pin(23);
        set_high_pin(23);
        while (1) {
            if (read_pin(25))
              invert_pin(23);
            waitcnt((CLKFREQ/4)+CNT);
        }
        return 0;
    }    
    
  • jazzedjazzed Posts: 11,803
    edited 2011-11-10 09:08
    Rick, it's not necessarily important in the cases you present, but generally a macro input symbol should be surrounded with parens in the definition.

    For example, set_input_pin should be written as: #define set_input_pin(pin) _DIRA &= ~(1<<(pin))

    The pin parameter is just a textual expansion. To ensure you get what you want, parens is used. This protects the user from situations like set_input_pin(25+n). In C the order of operations will cause a different result from SPIN.
  • David BetzDavid Betz Posts: 14,516
    edited 2011-11-10 09:11
    Since we're using GCC we could define all of these as inline functions. This would make the definitions a bit less obscure than with macros especially if they can't be done all on one line. For instance, here are some functions I wrote a while back:
    #include <stdint.h>
    #include "propeller.h"
    
    __inline__ void PinHigh(int pin)
    {
        uint32_t pin_mask = 1 << pin;
        OUTA |= pin_mask;
        DIRA |= pin_mask;
    }
    
    __inline__ void PinLow(int pin)
    {
        uint32_t pin_mask = 1 << pin;
        OUTA &= ~pin_mask;
        DIRA |= pin_mask;
    }
    
    __inline__ int PinIn(int pin)
    {
        uint32_t pin_mask = 1 << pin;
        DIRA &= ~pin_mask;
        return (INA & pin_mask) ? 1 : 0;
    }
    
    __inline__ void PinOut(int pin, int state)
    {
        uint32_t pin_mask = 1 << pin;
        OUTA = (OUTA & ~pin_mask) | (state ? pin_mask : 0);
        DIRA |= pin_mask;
    }
    
    __inline__ void PinDir(int pin, int direction)
    {
        uint32_t pin_mask = 1 << pin;
        DIRA = (DIRA & ~pin_mask) | (direction ? pin_mask : 0);
    }
    
    __inline__ int PinGetDir(int pin)
    {
        uint32_t pin_mask = 1 << pin;
        return (DIRA & pin_mask) ? 1 : 0;
    }
    
    __inline__ int PinToggle(int pin)
    {
        uint32_t pin_mask = 1 << pin;
        OUTA ^= pin_mask;
        return (OUTA & pin_mask) ? 1 : 0;
    }
    
    __inline__ int PinReverse(int pin)
    {
        uint32_t pin_mask = 1 << pin;
        DIRA ^= pin_mask;
        return (DIRA & pin_mask) ? 1 : 0;
    }
    
    __inline__ void PinHighs(int high, int low)
    {
        uint32_t pin_mask = ((1 << (high - low + 1)) - 1) << low;
        OUTA |= pin_mask;
        DIRA |= pin_mask;
    }
    
    __inline__ int PinLows(int high, int low)
    {
        uint32_t pin_mask = ((1 << (high - low + 1)) - 1) << low;
        OUTA &= ~pin_mask;
        DIRA |= pin_mask;
    }
    
    __inline__ void PinIns(int high, int low)
    {
        uint32_t pin_mask = ((1 << (high - low + 1)) - 1) << low;
        DIRA &= ~pin_mask;
        return (INA & pin_mask) >> low;
    }
    
    __inline__ void PinOuts(int high, int low, int states)
    {
        uint32_t pin_mask = ((1 << (high - low + 1)) - 1) << low;
        DIRA |= pin_mask;
        OUTA = (OUTA & ~pin_mask) | ((states << low) & pin_mask);
    }
    
    __inline__ void PinDirs(int high, int low, int directions)
    {
        uint32_t pin_mask = ((1 << (high - low + 1)) - 1) << low;
        DIRA = (DIRA & ~pin_mask) | ((directions << low) & pin_mask);
    }
    
    __inline__ int PinGetDirs(int high, int low)
    {
        uint32_t pin_mask = ((1 << (high - low + 1)) - 1) << low;
        return (DIRA & pin_mask) >> low;
    }
    
    __inline__ int PinToggles(int high, int low)
    {
        uint32_t pin_mask = ((1 << (high - low + 1)) - 1) << low;
        return ((OUTA ^= pin_mask) & pin_mask) >> low;
    }
    
    __inline__ int PinReverses(int high, int low)
    {
        uint32_t pin_mask = ((1 << (high - low + 1)) - 1) << low;
        return (DIRA ^= pin_mask) >> low;
    }
    
  • mindrobotsmindrobots Posts: 6,506
    edited 2011-11-10 09:12
    Thank you! Good stuff! The road to enlightenment stretches out before me!
  • jazzedjazzed Posts: 11,803
    edited 2011-11-10 09:23
    Jeff, you should also note the comments I made about #define parameters in this post: http://forums.parallax.com/showthread.php?135658-New-to-C-...-check-in-here&p=1050448&viewfull=1#post1050448

    Programmer's Notepad is a nice editor. I was able to define Ctrl+Shift+C for compile and Ctrl+Shift+D for download. There are some issues with that though for bigger programs and I cant get our terminal to work. I see Ctrl+Shift+K for killing an external program that may misbehave - it is useful.
    Thanks to Eric and Steve our header definitions are looking really good now, the header really makes the Spin to C conversions of the PEK Labs earlier examples a breeze to convert. I would say what we have will get us through 90% of Chapter 4. Things get really interesting in Chapter 5 when we get into methods and cogs, not quite ready on my end yet but there will be info posted here very soon. In the mean time here is a screen shot of the updated header file "myheader.h"

    Jeff T.

    EDIT: Kevin Wood suggested several good programs for typing and editing code files and headers, I chose Programmers Notepad which is a free download, personally I like it very much.
Sign In or Register to comment.