Shop OBEX P1 Docs P2 Docs Learn Events
Frustrations With Porting Spin to C (Using FlexGUI) [SOLVED] — Parallax Forums

Frustrations With Porting Spin to C (Using FlexGUI) [SOLVED]

JonnyMacJonnyMac Posts: 9,102
edited 2019-12-23 19:16 in Propeller 1
Having the desire to share my large library of Spin objects with those who prefer C, I decided to start by porting a my most recent objects for the TM1637 and TM1638 display drivers. I wrote Spin objects and test code for both devices in less than a day. Now, I've been programming in Spin -- almost every day -- for the last 13 years, so I'm pretty good at it.

While I don't routinely use C, I have used it enough to understand all but the most obtuse syntax rules, and over the years I have ported a lot of C code from other micros to the Propeller. Going from Spin -- except for very special cases -- is supposed to be easy; C dominates the programming world, it syntax is light and easy, etc., etc....

...my experience this week has been nothing but frustration.

I'm looking for guidance. And by that, I don't mean telling me to run my Spin code through some automated tool to do the conversion -- that's antithetical to deep leaning in my opinion. This exercise in frustation has been about learning, but I've had too much in the way of frustration and too little in the way of learning (something new).

I did get my C library for the TM1637 (2-wire) working after pounding my head on the desk dealing with SimpleIDE. Today I decided to try it in FlexGUI and, to my surprise, the frustrations are starting all over. I really didn't expect this after getting it to work under SimpleIDE.

These are the steps I took:
1. I created a separate library folder so that my custom code wouldn't be wiped out by replacing the FlexGUI folder. (C:/MyPrograms/jm_libc)
2. I copied my .h and .c library files to that folder
3. I added that folder to the library folders list in FlexGUI
4. I wrote a little test code just to test the library connection
#include "propeller.h"
#include "tm1637.h"


void main()
{

  while (1) {
  }
}

Click "Compile for P1" -- so far, so good. Next, I added a line to connect to the device.
#include "propeller.h"
#include "tm1637.h"


void main()
{
  tm1637_setup(4, 5, 6);

  while (1) {
  }
}

... and things blow up. Why?

"C:/MyPrograms/flexgui/bin/fastspin" -l -O2 -I "C:/MyPrograms/flexgui/include" -I "C:/MyPrograms/Parallax Inc/Propeller Tool v1.3.2/Library" -I "C:/MyPrograms/jm_libc" "D:/programming/C/tm1637_demo.c"
Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2019 Total Spectrum Software Inc.
Version 4.0.5 Compiled on: Dec 19 2019
tm1637_demo.c
D:/programming/C/tm1637_demo.c:14: error: unknown identifier tm1637_setup used in function call
D:/programming/C/tm1637_demo.c:14: error: Unknown symbol tm1637_setup
child process exited abnormally
Finished at Sun Dec 22 12:03:55 2019

Clearly, that function IS defined and implemented -- why is the compiler unhappy here?

Comments

  • RaymanRayman Posts: 14,640
    edited 2019-12-22 20:50
    Is line#185 in tm1637.c missing a semicolon?
          buffer[col] = segs                                        // save to buffer
          tm1637_write(segs);                                       // write to display
          if (++col == size)                                        // check for end of display
    
  • JonnyMac wrote: »
    While I don't routinely use C, I have used it enough to understand all but the most obtuse syntax rules, and over the years I have ported a lot of C code from other micros to the Propeller. Going from Spin -- except for very special cases -- is supposed to be easy; C dominates the programming world, it syntax is light and easy, etc., etc....

    ...my experience this week has been nothing but frustration.

    Can I start writing something I wanted to write since a long time ? Don't want to offend anyone.
    I'm amazed at how much efforts people put into learning all the new weird and esoteric languages but always complain about how diffcult and obscure C (or C++) is.
    Like any other language, C requires learning. How do you have learned to program in Spin ? I believe you weren't born with Spin skills already into your brain, you readed some manual, wrote some elementary code, experimented with it, gradually enhanced your skills. You need to do the same with C.
    In my case, I'm always frustraded when I have to write Spin code, a language I find with a lot of nonsense and with that weird convention that makes indentation a requirement! However I'm programming in C since I was 15 (now I'm 50) and Spin occasionally only when absolutely needed, so most of my frustration comes from inexperience.
    I'm looking for guidance. And by that, I don't mean telling me to run my Spin code through some automated tool to do the conversion -- that's antithetical to deep leaning in my opinion. This exercise in frustation has been about learning, but I've had too much in the way of frustration and too little in the way of learning (something new).

    I did get my C library for the TM1637 (2-wire) working after pounding my head on the desk dealing with SimpleIDE. Today I decided to try it in FlexGUI and, to my surprise, the frustrations are starting all over. I really didn't expect this after getting it to work under SimpleIDE.

    Your main error here is that you are relying on an IDE that hides most of the underlying details of the C build chain. SimpleIDE, like the Arduino IDE (don't know FlexGUI but I believe it does something similar), implements some "magic" to automatically build and link libraries, however these details needs to be known otherwise you'll always fail to understand why your code doesn't work as you expect.

    The first thing you need to do is throw away the IDE and compile your code with command line tools, like:
    propeller-elf-gcc -mlmm -std=c99 -Os -Wall -o tm1637_demo.elf tm1637_demo.c tm1637.c
    

    This command will compile and link all the source codes and produces the elf executable. You should also need to know what the command line parameters means because they can have effects on pre-compiled libraries if not used properly.

    Now you need to use the loader to write the binary to the Propeller eeprom:
    propeller-load -p /dev/ttyACM0 -e tm1637_demo.elf
    

    Once you have practiced with these, you can learn how to produce object codes from source files, how to build a library and how to link them to other sources to produce the final executable. Learning how to use a Makefile is also very important with C. In other words, start with the basics.

    After that you can start to use an IDE that does some of the work for your hiding the details (but I believe that you won't do that).

    About your specific problem, the source files you have attached can be compiled without problems (well, there is a missing semicolon but the compiler will tell you where). If SimpleIDE (or something else) complains that it can't find a method probably means that it can't link the library, maybe because you didn't follow the convention used by that IDE to find the libraries.
  • RaymanRayman Posts: 14,640
    I would change the title of this thread to include "Flex C" or "FlexGui" so that ersmith sees it...
  • RaymanRayman Posts: 14,640
    I does look like a bug in FlexGui to me too...
  • Including a file, does exactly that. Instead of the line #include "tm1637.h" the content from "tm1637.h" is copied.
    You compile only "tm1637_demo.c" and "tm1637.h", so the compiler knows the name of function "tm1637_setup", but the function is not compiled.
    You have to add "C:/MyPrograms/jm_libc/tm1637.c to your commandline.

    This should compile, after adding the semicolon:
    "C:/MyPrograms/flexgui/bin/fastspin" -l -O2 -I "C:/MyPrograms/flexgui/include" -I "C:/MyPrograms/Parallax Inc/Propeller Tool v1.3.2/Library" -I "C:/MyPrograms/jm_libc" "D:/programming/C/tm1637_demo.c" "C:/MyPrograms/jm_libc/tm1637.c

    Problem of flexgui is, as I know, that you can not make a project and add all your files you need.
  • macca beat me to it. There is a lot of hidden stuff that is occurring behind the scenes, or under the hood, like the build chain.

    Now, before SimpleIDE became "simple", there was only a "Project Manager" mode. As I recall, in SimpleIDE, the bottom left side, if you click on the icon, it will put SimpleIDE into Project Manager mode. Now the IDE becomes not so "simple", you can do a lot more stuff.

    For your tm1637 program you could have:
    #include "propeller.h"
    #include "tm1637.h"
    
    
    void main()
    {
      tm1637_setup(4, 5, 6);
    
      while (1) {
      }
    }
    
    In the Project Manager window, on the left side you would see something like:
    tm1637.side
    tm1637.c
    pressing the right button of the mouse allows you to add a file to the build chain. In this case you may want to change your tm1637. c to maybe tm1637_p.c and that would be added to the build chain.

    I have not tried doing that, but I believe that should compile your program correctly.

    Yea, to bad jazzed did not think about adding the ability of adding PASM code and have the program convert it to some functional C code. Man, that would have simplified the use of existing PASM drivers code. I bet jazzed probably mentioned that to Parallax, but they more than likely shut him down.

    Ray
  • I'm just starting to play with flexgui, but it appears that it uses _IMPL to tell it where additional files are. In your header file, change the function prototype for tm1637_setup as follows:
    uint8_t tm1637_setup(uint8_t cpin, uint8_t dpin, uint8_t ncols) _IMPL("samples/tm1637.c");
    
    In my case I put your code in the flegui samples directory. If you have it somewhere else you will need to change "samples" to your directory path. This seem to work OK for me.
  • flexgui does not (yet) support multi-source-file compiles, but fastspin, which flexgui uses for compiles does, as noted above! But, as an example (on my macOS system), I added the path to the tm1673.c file within the Configure Commands dialog of flexgui and it compiles with just the addition of that semicolon on line 185... It's just an example workaround but does show the possibility of flexgui to build multi-file sources (hint, hint to ersmith) :-)

    FlexGuiConfigureCommands.png

    dgately
    1136 x 791 - 413K
  • RaymanRayman Posts: 14,640
    That worked for me too.
    Pain though...
    Guess you have to have "Project" file for C...
  • JonnyMacJonnyMac Posts: 9,102
    edited 2019-12-22 22:21
    @Rayman Yeah, I will add FlexGUI or FastSpin to the title. I'm still going on the theory that I'm at at fault -- just looking for the reason why so I can learn from it and keep moving. And thank you for directing me to the missing semicolon with bludgeoning me for my lack of experience. :)

    @dnalor This is where I'm confused; my expectation that including the custom library path would handle that. I wonder if this is why Ray thinks FastSpin may have a bug.

    @"Dave Hein" and @dgately Thank you for your suggestions.
  • RaymanRayman Posts: 14,640
    edited 2019-12-22 22:18
    No, it's not a bug, I get it now, it's just what dnalor said...

    I'm just used to doing C++ in Visual Studio where I have all the files I need in the project anyway...
  • JonnyMacJonnyMac Posts: 9,102
    edited 2019-12-22 22:27
    Got it. Long term, I do want to understand the intricacies of command-line tools so that I can use Geanie, which is my personal favorite editor (I use it for Python and C programming on my PC). As has been pointed out, IDEs often hide details from us.
  • For C, it seems like a simple solution for FlexGUI would be to automatically compile *.c files with the same name and directory path as included *.h files. This could be overridden by specifying the source file with _IMPL. Maybe Eric has some other solution in mind.
  • Where in the hell did anybody get the idea that something like C or g-d help us C++ was a good place to teach newbies how to code? I want to run and find a basement to hide in when I hear the word "toolchain." I realize the market bespoke otherwise but Spin and the PropTool were the right idea, just as the PBasic dev tools were before. What is it with this language that was designed so it could be compiled by a PDP-8 that people "like" so much? Maybe it could use curly brackets for a few more purposes. Oh wait, there's C++, which I think means C + much grief.
  • I think most of the confusion has been cleared up by other posters, but to summarize / re-iterate:

    (1) #include just literally copies the contents of the .h file into the source at the point where the #include is seen. In standard C #include does nothing to arrange that the libraries described by the .h file will actually be linked into the code.

    (2) This is confusing for newcomers because the "standard" C libraries (described by <stdio.h> and similar header files) *are* automatically linked, so they naturally expect that their own libraries will get this treatment. But they don't.

    (3) Different compilers/toolchains/IDEs have different ways of overcoming this problem. The portable solution is to use a command line or an IDE that lets you link multiple files together, and to specify all of the source files and libraries that you need explicitly. SimpleIDE does some kind of magic behind the scenes that (usually) causes it to compile a .c file when the corresponding .h is included, but I don't know exactly what that is. Visual C has a #pragma to specify that a library should be linked when a .h is included; I'll probably (eventually) try to implement something like that. For now, FlexC has a special define _IMPL() (defined in <compiler.h>) that says where a function is implemented. So if you write something like:
    // this is in tm1637.h
    #include <compiler.h>
    ...
    int tm1637_setup(int x, int y, int z) _IMPL("tm1637.c");
    
    then a #include "tm1637.h" will automatically make sure tm1637.c is compiled as well. This is non-portable, but unfortunately there is no portable solution in C :(.
  • JonnyMacJonnyMac Posts: 9,102
    edited 2019-12-23 19:16
    (2) This is confusing for newcomers because the "standard" C libraries (described by <stdio.h> and similar header files) *are* automatically linked, so they naturally expect that their own libraries will get this treatment. But they don't.
    Guilty -- hence my confusion.

    Thanks for the clarification. I've got to get back to being productive, so my adventures in programming the Propeller with C -- for the time being, anyway -- have come to an end.
Sign In or Register to comment.