After going in circles for quite some time, I have decided to get serious about this project. So I am digging in deep, firmly planting my feet, and taking the gloves off.
My strategy really has not changed much, because I will be starting this new effort, with the same critical core components, which are the DDA filles, the DDA math files, the DDA queue files, the G-Code parser, and the G-Code processor. However, I have also decided to return to the original plan and eliminate conditional compiling. By eliminating the conditional compiling, I will also be eliminating many options offered by the original Teacup firmware. Of course all the options would be nice, but since the original source code is so deeply entrenched in Arduino and AVR support, it would make a complete Propeller port, an extremely daunting task. By porting only the critical components, functional but limited Propeller firmware may be developed for 3D printing. After functional firmware has been developed, other options may be added to enhance the firmware. According to the documentation, ACCELERATION_RAMPING with LOOKAHEAD, appears to be the way to go and that is the type of port that'll be my goal. Additionally, when it comes to parsing the G-Code, I believe the REQUIRE_LINENUMBER and the REQUIRE_CHECKSUM options should be supported, for debugging purposes. As for debugging, there is also the DEBUG option, but this option will initially be unavailable, because the original debug source code will have to be altered to support full duplex serial. However providing DEBUG support should be fairly simple, after the core components are compiling. Until the key components are compiling, all DEBUG source code will be commented out, but left in place, for future reference. When a successful compile is achieved, debugging will then be altered to support full duplex serial and then become available for debugging purposes.
As you have seen in my previous posts, it was originally my intention, to port Teacup into SPIN, but after long and deep consideration, I have decided to port it in C. There are several reasons for choosing C as the programming language, which I will not discuss, because I don't suppose they are important. I am just letting you all know which direction I am heading. So for a large section of the day, I have been cleaning and editing the key files for this project, making the code more legible, by aligning indents, seperating condtions, adding white space, and removing all conditional compilation. When I have all the files the way I want them, I will then begin to edit out the remaining problems until a successful compilation is achieved. This will include making stub functions as Dave suggested and making sure that all variables and constants are clearly defined.
I did not mention it in my last post, but my port will also include provisions for limit switches on each end of X, Y, and Z axes. While cleaning and editing gcode_process.c, I came across a surprise. The file gcode_process.c relies heavily upon home.c, which provides homing routines for all the axes, providing the limit switches are defined for a given axis. After looking over home.c, it appears that porting that file should be relatively simple. So in addition to the forementioned files, home.c and home.h will now be added, which will provide homing capabilities.
First off, let me say that I was wrong about a couple things. At this point, I am really beginning to see how important the conditional compilations are to this project. Until just recently, I was under the assumption, that the Teacup settings were a set and forget configuration. The deeper I dig into the source code, the more I realize that the configuration settings are sometimes meant to be just temporary settings, and that this firmware was not intended to be simply a set and forget configuration from jump street. However, I am fairly certain that once you have it tuned, you will rarely have to alter the settings. At first, I saw the conditional compilations as a hinderance, but now I am beginning to see them as an asset. By leaving much of the conditional compilation in place, the firmware can be adaptable to many different types of setups, with each configuration being unique to any given particular machine.
So upto this point, I have still been spinning my wheels and going nowhere fast. I have wasted a lot of time and useless effort, just getting a grasp of the process and firmware. And I must say that I always find something new and I must admit that it is a very interesting piece of software.
Anyhow, I got beat up that round and all the previous rounds, but I am not giving up. I just needed to take a few licks, to find out what kind of opponent I was up against. So I will now begin a new round, with conditional compilation.
As for the necessary files, the list has changed to include several more very important files. The new list is as follows:
Instead of wasting more of my time on useless coding efforts, I have been taking a more in depth look into the Teacup firmware. As mentioned, Arduino and AVR support is wrapped within the software pretty tightly, or at least it appeared that way. After determining the options that I wanted to support, I then began to determine the necessary files to support these options, and then I began to look for the proper location to start inserting Propeller specific code. As it turns out, or so I now believe, the porting process should begin within pinio.h.
At first glance, or should I say for quite some time, pinio.h seemed a bit overwhelming, and I was having a bit of trouble understanding, the process, the settings, etc... As I see it now, pinio.h sets up the whole runtime environment, by taking the settings established in the config.h file and applying them to functions throughout the firmware, by defining these funtions according to the settings themselves, within the pinio.h file.
Considering a C port, using SimpleIDE, it appears that pinio.h can be easily altered with the inclusion of simpletools.h. Whereas the READ(s) and WRITE(s) that now exist within pinio.h, could be replaced with functions available from the simpletools library. By replacing these READ(s) and WRITE(s) with simpletools functions, it should define further functions within the firmware that the Teacup frmware needs to operate, thus making a Teacup port actually feasible, without all the additional drudgery of creating stub functions, and writing code that has already been written. Or so I think
Although I have not verified it, I do believe that most of the pins utilized within config.h, are either input or output pins within an Arduino or AVR environment, so there direction does not need to be established, whereas with the Propeller these directions will need to be established, but I have not yet determined the proper location for this. I suppose that if all the pins were being accessed by one cog, everything could be controlled pinio.h. Now I also suppose that cog usage, would also be the determing factor of what should actually be defined in pinio.h, and perhaps there should be files similar to pinio.h for each cog utilized by the necessary pins.
I am now expanding the discussion of the previous post a bit further.....
I must admit, even though I am sure it is obvious, that I know zilch about Arduino and I was wrong when I stated,
Although I have not verified it, I do believe that most of the pins utilized within config.h, are either input or output pins within an Arduino or AVR environment, so there direction does not need to be established
Upon further digging, I found READ and WRITE defined within arduino.h, which contains several IO macros. So basically, arduino.h is the setup stage for all communication with the various pins utilized. As many of us already know, mendel.c is starting point of Teacup, because it contains the main function. The io_init function of mendel.c relies heavily upon arduino.h, config.h, and pinio.h, for establishing pins utilized, pin directions, pin states, and setting up functions for easily communicating and interfacing with the various pins.
I mentioned in the previous post that
Considering a C port, using SimpleIDE, it appears that pinio.h can be easily altered with the inclusion of simpletools.h. Whereas the READ(s) and WRITE(s) that now exist within pinio.h, could be replaced with functions available from the simpletools library. By replacing these READ(s) and WRITE(s) with simpletools functions, it should define further functions within the firmware that the Teacup frmware needs to operate, thus making a Teacup port actually feasible, without all the additional drudgery of creating stub functions, and writing code that has already been written. Or so I think
While I firmly believe the proceeding statement to be true, this will not affect the use of SET_OUTPUT utilized within mendel.c and pinio.h, because it is defined within arduino.h. By altering both arduino.h and pinio.h to match the functions of the simpletools library, I think a very large portion of the Teacup software can remain as it is.
EDIT: It almost appears that only the arduino.h file needs to be modified. Wouldn't that be a hoot
I am now at a point where I believe the main portion of the port will be the altering of the following code to become Propeller friendly:
#ifndef MASK
/// MASKING- returns \f$2^PIN\f$
#define MASK(PIN) (1 << PIN)
#endif
/*
magic I/O routines
now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0);
*/
/// Read a pin
#define _READ(IO) (IO ## _RPORT & MASK(IO ## _PIN))
/// write to a pin
#define _WRITE(IO, v) do { if (v) { IO ## _WPORT |= MASK(IO ## _PIN); } else { IO ## _WPORT &= ~MASK(IO ## _PIN); }; } while (0)
/// toggle a pin
#define _TOGGLE(IO) do { IO ## _RPORT = MASK(IO ## _PIN); } while (0)
/// set pin as input
#define _SET_INPUT(IO) do { IO ## _DDR &= ~MASK(IO ## _PIN); } while (0)
/// set pin as output
#define _SET_OUTPUT(IO) do { IO ## _DDR |= MASK(IO ## _PIN); } while (0)
/// check if pin is an input
#define _GET_INPUT(IO) ((IO ## _DDR & MASK(IO ## _PIN)) == 0)
/// check if pin is an output
#define _GET_OUTPUT(IO) ((IO ## _DDR & MASK(IO ## _PIN)) != 0)
Source: Teacup firmware - arduino.h
EDIT: I could probably use a little help with this, if anyone is so inclined
EDIT: Here is the funny thing.... And I am sure you will all get a good laugh.... config.h states the following:
If you want to port this to a new chip, start off with arduino.h and see how you go
Source: Teacup firmware - config.h
I read this comment numerous times, but I just did not understand where to begin. After a lot of research and studying of the firmware, now I understand
EDIT: In an effort to provide an easier understanding, I have altered the code above as follows:
#define MASK(PIN) (1 << PIN)
/// Read a pin
#define _READ(IO) (IO ## _RPORT & MASK(IO ## _PIN))
/// write to a pin
#define _WRITE(IO, v)
do
{
if(v)
{
IO ## _WPORT |= MASK(IO ## _PIN);
}
else
{
IO ## _WPORT &= ~MASK(IO ## _PIN);
};
}
while (0)
/// toggle a pin
#define _TOGGLE(IO)
do
{
IO ## _RPORT = MASK(IO ## _PIN);
}
while (0)
/// set pin as input
#define _SET_INPUT(IO)
do
{
IO ## _DDR &= ~MASK(IO ## _PIN);
}
while (0)
/// set pin as output
#define _SET_OUTPUT(IO)
do
{
IO ## _DDR |= MASK(IO ## _PIN);
}
while (0)
/// check if pin is an input
#define _GET_INPUT(IO) ((IO ## _DDR & MASK(IO ## _PIN)) == 0)
/// check if pin is an output
#define _GET_OUTPUT(IO) ((IO ## _DDR & MASK(IO ## _PIN)) != 0)
After further examination and considering the unknowns of the macros defined within arduino.h, I am now inclined to believe that a modification of pinio.h would be the easiest alternative for porting. In addition to pinio.h, there are several other locations within the Teacup firmware, where the READ and WRITE functions are utilized, as well as some of the additional functions provided by arduino.h. I do believe a Propeller port would be much easier to understand, if all these existing functions were changed to simpletools.h functions, where they are being used.
EDIT: Although I am uncertain how these alterations will affect the program size, when defined or included in multiple locations.
By the time I got back here I had already written something up, but I am unsure of it.
In the past, I normally just used defines for assigning constant values, so I am unsure if the following would work, because it utilizes functions, but I think it will. Anyhow, I believe something similar to the following is the key to porting this monster.
Most of these calls are made from either mendel.c or pinio.h, with very few exceptions. And providing this code is acceptable, all references of "#include arduino.h" should be changed to "#include PropelledTeacup.h", or completely removed. Additionally, all references to the simulator, avr, or arduino specific code should be obliterated.
#include "simpletools.h"
/////////////////////////////////////////////////
// Propeller Specific
/////////////////////////////////////////////////
/// Read a pin
#define _READ(IO) get_output(IO)
/// Write to a pin
#define _WRITE(IO, v) set_output(IO, v)
/// set pin as input
#define _SET_INPUT(IO) set_direction(IO, 0)
/// set pin as output
#define _SET_OUTPUT(IO) set_direction(IO, 1)
/////////////////////////////////////////////////
/// Read a pin wrapper
#define READ(IO) _READ(IO)
/// Write to a pin wrapper
#define WRITE(IO, v) _WRITE(IO, v)
/// set pin as input wrapper
#define SET_INPUT(IO) _SET_INPUT(IO)
/// set pin as output wrapper
#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
/////////////////////////////////////////////////
#ifndef BSS
#define BSS __attribute__ ((__section__ (".bss")))
#endif
EDIT: I will try both of them. I believe your macros would leave a much smaller footprint, because if I am not mistaken, that would only require the include of propeller.h.
EDIT: Additionally, I have discovered that _TOGGLE(IO), _GET_INPUT(IO), and _GET_OUTPUT(IO) are unnecessary.
Here is a header file that includes the macros that Dave altered. Even though _TOGGLE(IO), _GET_INPUT(IO), and _GET_OUTPUT(IO) are not used within the Teacup firmware (or at least in the files that I intend to use), I have decided to retain them, because these macros and functions may become useful during the port. This header file only requires the include of propeller.h, whereas the previous header file required simpletools.h. As with the previous header file, all references to the simulator, avr, or arduino specific code should be obliterated.
Additionally, this file is named PropellerizedTeacup.h
/*!
\file
\brief pin definitions and I/O macros
*/
#ifndef _PROPELLERIZEDTEACUP_H
#define _PROPELLERIZEDTEACUP_H
#include <propeller.h>
#ifndef BSS
#define BSS __attribute__ ((__section__ (".bss")))
#endif
#ifndef MASK
/// MASKING- returns \f$2^PIN\f$
#define MASK(PIN) (1 << PIN)
#endif
/*
magic I/O routines
now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0);
*/
/// Read a pin
#define _READ(IO) ((INA & MASK(IO ## _PIN)) != 0)
/// Write to a pin
#define _WRITE(IO, v) OUTA = (OUTA & ~MASK(IO ## _PIN)) | ((v & 1) << (IO ## _PIN))
/// toggle a pin
#define _TOGGLE(IO) OUTA ^= MASK(IO ## _PIN)
/// set pin as input
#define _SET_INPUT(IO) DIRA &= MASK(IO ## _PIN)
/// set pin as output
#define _SET_OUTPUT(IO) DIRA |= MASK(IO ## _PIN)
/// check if pin is an input
#define _GET_INPUT(IO) ((DIRA & MASK(IO ## _PIN)) == 0)
/// check if pin is an output
#define _GET_OUTPUT(IO) ((DIRA & MASK(IO ## _PIN)) != 0)
// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
/// Read a pin wrapper
#define READ(IO) _READ(IO)
/// Write to a pin wrapper
#define WRITE(IO, v) _WRITE(IO, v)
/// toggle a pin wrapper
#define TOGGLE(IO) _TOGGLE(IO)
/// set pin as input wrapper
#define SET_INPUT(IO) _SET_INPUT(IO)
/// set pin as output wrapper
#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
/// check if pin is an input wrapper
#define GET_INPUT(IO) _GET_INPUT(IO)
/// check if pin is an output wrapper
#define GET_OUTPUT(IO) _GET_OUTPUT(IO)
#endif /* _PROPELLERIZEDTEACUP_H */
As I learn about various aspects of the Teacup firmware and as time passes, my goals of this project have changed significantly, or should I say for the time being.
As mentioned, I know nothing about Arduino, so without spending a bunch of time learning about Arduino or unless someone takes the time to educate me, all I can do is make various assumptions. At this current point of time, I am assuming that the Teacup firmware is a single threaded process, that runs without the benefit 8 cogs, or even two parallel processes, mostly because of my lack of knowledge about Arduino and the lack of evidence throughout the firmware, but I could be wrong.
Anyhow, my current goal is to match the operation of Teacup, without taking advantage of all the Propellers attributes. If I can manage that task, then I will see about altering some code to make better use of the Propeller's resources. However this may change as my efforts develop. Of course there are a few exceptions, such as some name changes for the various files, but most of them will remain the same for easy reference, at least for now. However, right from the start, I will be renaming mendel.c to forger.c, to represent the name of the 3D printer prototype that I am building. If I succeed with this port, I will then be referring to the firmware, as the Forger Firmware. As previously mentioned, and please do not forget, my efforts will be geared towards the controller described within this thread: http://forums.parallax.com/showthread.php/155404-Input-Needed-Combining-Propeller-Proto-Board-Prop-DIP-40-and-ADC-for-3D-Printer. However, I am fairly certain that various configurations may be obtained by altering config.h.
With the assistance of Dave Hein, PropellerizedTeacup.h now exists. This file is intended to replace arduino.h, and this file is responsible for all pin settings and communication with the various IO pins that are utilized. Additionally, PropellerizedTeacup.h should allow for a fair amount of conditional compiling of the Teacup firmware for the Propeller.
As I see it now, the biggest remaining obstacle is the serial interface, which includes DEBUG, and it is intermingled throughout a large portion of the files. Before proceeding any futher, I will try determine what must be done to remove this huge obstacle, but it may not be as big of a problem as I believe it is.
Just in case anyone is silently following along and in reference to my previous post, the following list and attachment, contains references to the various serial interfaces of Teacup. And these references are just from the files that I may support. As you can clearly see, the serial interfaces are widespread.
Referring to my last two posts concerning the serial interfaces.....
Although I am not 100% certain, I am fairly certain that sermsg.h, sermsg.c, sersendf.h, and sersendf.c, can pretty much remain the way they are, with the following exceptions:
change all references of #include "serial.h" to #include <fdserial.h>
change all references of serial_writechar(uint8_t data) to fdserial_txChar (fdserial *term, int txbyte)
Someone please correct me if I am wrong
EDIT: However I am now thinking that this might be a better alternative
change all references of #include "serial.h" to #include "simpletext.h"
change all references of serial_writechar(uint8_t data) to putChar (char c)
EDIT: This was certainly a case of wishful thinking
EDIT: I just got sersend to output to the SimpleIDE terminal the following: sersendf_P(PSTR("rs N%ld Expected line number %ld\n"), 100, 200);
Alrighty folks, like everyone else, I have my strengths and weaknesses, and this is especially true when it comes to programming. Undoubtedly, there will be times during this project when I need help and this just happens to be another one of those times, because bit banging, bit shifting, and serial communication was never my expertise.
As I have mentioned in a few of my previous posts, I am now attempting to tackle the serial interface problems. I believe this is probably this biggest problem remaining, besides getting rid of all the interrupt stuff, and I know I will also need help with that to.
Anyhow, I have been attempting to get certain Teacup serial interface files to communicate with the simpletext library, and I have had partial success. Of course, partial success just won't cut the mustard.
In an effort to obtain some help and perhaps gain a little more traction with this project, I have created a SimpleIDE project, which should contain a solution to the serial interface problems associated with the Teacup port. However there are still problems to be resolved, as can be witnessed by the attached image.
Any and all effort that you may be willing to share to make the attached SimpleIDE project bulletproof, will be greatly appreciated.
EDIT: Please note that the following define can be removed from sersendf.h of the attached project, because it is not needed: #define pgm_read_word(x) (*((uint16_t *)(x)))
As I see it, passing uint16_t and int16_t data types to GET_ARG, is the cause of the warnings generated during the build process, whereas uint32_t and int32_t data types do not generate any warnings at all and pass right on through the build process.
Within sermsg.h, serwrite_uint16(v) and serwrite_int16(v) are defined as follows:
As you can clearly see, these short functions are simply defined by the long functions, and therefore they should be processed exactly the same way, except with different data types sent during the calls.
At this point, I am assuming that these two defines are actually just garbage, and that the uint16_t and int16_t data types should just be passed to the serwrite_uint32 and serwrite_int32 functions in the first place.
I do not understand why it was done this way to provide warnings and code collapse. Either way, I am going to toy around with eliminating the serwrite_uint16(v) and serwrite_int16(v) functions and see what happens.
I still need to thoroughly test this, but I believe this is the fix for making sersendf.c compatible with the simpletext library. Providing the format string is correct, this code should build without warnings.
Don't blame me for the code layout... Mine looks neat
/** \file sersendf.c
\brief Simplified printf implementation
*/
#include "sersendf.h"
#include <stdarg.h>
#include "simpletext.h"
#include "sermsg.h"
/** \brief Simplified printf
\param format pointer to output format specifier string stored in FLASH.
\param ... output data
Implements only a tiny subset of printf's format specifiers :-
%[ls][udcx%]
l - following data is (32 bits)\n
s - following data is short (8 bits)\n
none - following data is 16 bits.
u - unsigned int\n
d - signed int\n
q - signed int with decimal before the third digit from the right\n
c - character\n
x - hex\n
% - send a literal % character
Example:
\code sersendf_P(PSTR("X:%ld Y:%ld temp:%u.%d flags:%sx Q%su/%su%c\n"), target.X, target.Y, current_temp >> 2, (current_temp & 3) * 25, dda.allflags, mb_head, mb_tail, (queue_full()?'F':(queue_empty()?'E':' '))) \endcode
*/
void sersendf_P(PGM_P format, ...)
{
va_list args;
va_start(args, format);
uint16_t i = 0;
uint8_t c = 1;
uint8_t j = 0;
while((c = pgm_read_byte(&format[i++])))
{
if(j)
{
switch(c)
{
case 's':
j = 1;
break;
case 'l':
j = 4;
break;
case 'u':
if(j == 4)
{
serwrite_uint32((uint32_t)va_arg(args, uint32_t));
}
else
{
serwrite_uint16((uint16_t)va_arg(args, uint32_t));
}
j = 0;
break;
case 'd':
if(j == 4)
{
serwrite_int32((int32_t)va_arg(args, int32_t));
}
else
{
serwrite_int16((int16_t)va_arg(args, int32_t));
}
j = 0;
break;
case 'c':
putChar((uint16_t)va_arg(args, uint32_t));
j = 0;
break;
case 'x':
putStr(PSTR("0x"));
if(j == 4)
{
serwrite_hex32((uint32_t)va_arg(args, uint32_t));
}
else if(j == 1)
{
serwrite_hex8((uint8_t)va_arg(args, uint32_t));
}
else
{
serwrite_hex16((uint16_t)va_arg(args, uint32_t));
}
j = 0;
break;
// An original comment
//case 'p':
//serwrite_hex16(GET_ARG(uint16_t));
case 'q':
serwrite_int32_vf((int32_t)va_arg(args, int32_t), 3);
j = 0;
break;
default:
putChar(c);
j = 0;
break;
}
}
else
{
if(c == '%')
{
j = 2;
}
else
{
putChar(c);
}
}
}
va_end(args);
}
Providing the format string is correct, this code should build without warnings.
I sure was wrong with that statement. The compiler spits out all kinds of warnings, with any kind of formatting, but the code holds up without aborting. As I see it, the compiler really does not like different data types when using stdarg.h, and therefore issues warnings.
I have reconfigured the test program to show how everything works, utilizing sermsg and sersendf, as well as simpletext. With the exception of the warnings, and unless I am missing something, everything appears to be working well.
If there is one thing that I have learned during this attempted port, I learned that there are a lot of different issues to consider. If you make one bad choice, then all your work is for nothing, and you must start all over again, or at least that has been true for most of my choices. Luckily for me, it is not that bad, concerning my last bad choice..
If you have been following along, you will know that I am shooting for an ACCELERATION_RAMPING and a LOOKAHEAD port of the firmware. While both of these choices are good for 3D printing, I don't believe the same holds true for a standard CNC machine. Whereas the ACCELERATION_RAMPING would most likely be beneficial to a standard CNC machine, LOOKAHEAD could be very detrimental, because it joins moves together, to prevent excess oozing of the filament, at the end of a targeted move. In the case of a standard CNC machine, you will not have this oozing problem, and you definitely want to hit the target location. By eliminating all of the conditional compiling for LOOKAHEAD, I have essentially made the movement code useless for a standard CNC machine. However, luckily for me, after doing a little research, I have discovered that the only important files affected are dda.c and dda.h. Considering that I will most likely want to use these files for other projects besides 3D printing, I will now have to edit dda.c and dda.h once again, and leave the LOOKAHEAD conditional compiling in full working order.
While editing these two files are a bit of a pain, I realize that the situation could have been a lot worse.
Well folks, I have finally reached the point to where things are starting to get very complicated.
Porting the files analog.c, heater.c, temp.c, and timer.c, should be a real challenge.
In addition to getting very complicated, I have stumbled upon a major disappointment with the following code:
/// How often we overflow and update our clock.
/// With F_CPU = 16MHz, max is < 4.096ms (TICK_TIME = 65535).
#define TICK_TIME 2 MS
Source: timer.h
Although it may appear simple, this setting runs deep to the core of the firmware, or so it appears. This setting will affect all of the previously mentioned files, as well as dda_queue.c and dda.c. It appears to me that TICK_TIME has a maximum value of 65535, and if that is true, for simplicities sake, the fastest that I will be able to run the Propeller is 20MHz, but that is assuming a port that utilizes large portions of existing code and existing variables.
I definitely want to take full advantage of the Propeller's speed, but for now, I think I will take the easy road (yea right!), and limit the frequency to 20MHz, and later, when I have a much better understanding of it all, I can attempt to alter the code and make it 80MHz compatible.
EDIT: I just searched all the various configuration files that came with the Teacup firmware, and the highest setting I found for F_CPU was indeed 20MHz, and that was located in config.gen7-v1.1-v1.3.h and config.gen7-v1.4.h
Considering the number of views, I know there is curiousity amongst you.
However I am also curious, as to whether anyone else is digging through the Teacup files.
It sure would be nice to have a fellow collaborator about this time
As I have said earlier, I know nothing about Arduino, but according to the comments left by the author, timer.c utilizes two different timers, one for general activities, and another for clocking the step times, but they also refer to some type of comparator. Anyhow, I will have to do some more research, but I believe I will be setting up a cog for these two timers and do my counting with CTRA and CTRB. I am not sure how the comparator fits in there yet, but.....
With the exception of possibly setting CTRMODE to %11111, I cannot see how CTRA or CTRB will help me. Like I said, this will take some thought and research.
Now for the bad news OCRn has to be a whole number. If you end up with a decimal number it means that your desired timer will not be exact. The other thing is that your number has to be able to fit into the register. So 255 for an 8bit timers and 65535 for the 16bit timer.
A large portion of the Forger (formerly Teacup) Firmware now compiles for use on the Propeller chip. Here are some of the problems that remain:
All the files that were deeply embedded with Arduino specific code need to be rewritten and added to the project. Fairly large size project.
There is some commented Arduino specific code contained within the project files that needs to be reworked for the Propeller. Medium size project.
Replacing a few minor instances of the Arduino serial interface with the Propeller serial interface. Piece of cake.
For some odd reason, LOOKAHEAD is not communicating with the DDA. Haven't found it yet.
Change all 16 bit frequency limitations to 32 bit. Not sure how hard that will be or how deeply it goes.
All items that need attention will be in comments! The comments will contain a date in the form of //2/25/2015// or //2/25/2015//Bruce//. If you want to look at all the potential problems, just search the documents for Bruce or just a date.
@Dave Hein - I had to alter the macros a little to get it to compile, but your assistance helped greatly. All references of "IO ## _PIN" were changed to simply "IO".
For some odd reason, LOOKAHEAD is not communicating with the DDA. Haven't found it yet.
It is not communicating, because it is not compiling. I know this because there is no reference to it in the build status pane, and I also know that it contains errors which should show up in the build status pane. However, I still have not located the problem.
EDIT: I found it. At the top of dda_lookahead.c, make the following change:
FROM:
#ifdef LOOKAHEAD
#include "dda_lookahead.h"
TO:
#include "dda_lookahead.h"
#ifdef LOOKAHEAD
EDIT: With a few more dated comments, LOOKAHEAD is now communicating with the DDA
As you may know, I am not an expert C/C++ programmer, but I am certainly not a beginner either. One thing is for sure, there are certain parts of this firmware that can make your brain go numb, just by looking at the code. For example:
If you look a few lines before the DEFINE_HEATER macro you'll see the declaration of the heater_definition_t struct.
/// \struct heater_definition_t
/// \brief simply holds pinout data- port, pin, pwm channel if used
typedef struct {
volatile uint8_t *heater_port; ///< pointer to port. DDR is inferred from this pointer too
uint8_t heater_pin; ///< heater pin, not masked. eg for PB3 enter '3' here, or PB3_PIN or similar
volatile uint8_t *heater_pwm; ///< pointer to 8-bit PWM register, eg OCR0A (8-bit) or ORC3L (low byte, 16-bit)
} heater_definition_t;
The Prop only has one I/O Port, so the value of heater_port isn't important. Also, since PWM is done in software on the Prop, and there is no PWM register on the Prop, heater_pwm just needs to indicate whether PWM is to be used for this pin. So I would define DEFINE_HEATER on the Prop as
This is very similar to the previous macros that you helped me with.....
The whole concept is: User settings are defined in config.h and the various macros throughout Teacup pull in the defines of config.h and set the values where they are needed. By doing it that way, all user settings are located in one header file, so that a person with little or no C/C++ experience, can simply alter the settings in one file to match their machine, and build the project, instead of inserting the values in many different locations, throughout the source code.
EDIT: In fact, it would be nice to keep the user settings out of the firmware entirely, and perhaps do an sd card read of a configuration file and assign the values to variables at startup.
EDIT: Or perhaps, at startup, the firmware would look in various locations for the configuration file, like EEPROM (added with something like the file directive in SPIN), the root directory of the SD card, or even the GCODE file itself. And then I suppose the settings could also be configured over a serial connection.
EDIT: So when the firmware is ready, just burn the EEPROM with the firmware and look for the settings elsewhere.
Yes, I know about config.h. The sample config.h files use DEFINE_HEATER to add entries to the heaters[] array. I don't understand what you are getting at. You're not going to be able to port the Teacup software just by changing config.h. You are going to have to change other files to accommodate the differences between the AVR and the Prop. You might be able to minimize the changes by trying to emulate the AVR to a certain extent.
Maybe I misunderstood your comment about converting to "Propeller lingo". I thought you were asking for suggestions on how to handle the DEFINE_HEATER macro.
Yes, I know about config.h. The sample config.h files use DEFINE_HEATER to add entries to the heaters[] array. I don't understand what you are getting at.
My point is that I do not want to change the basic theory of operation. Even though I am basically setting this up for my current project, I also want the firmware to be adaptable for other machines, with simple changes to one file. So instead of definining heaters in the heater source, I want to keep them in the config file.
You are going to have to change other files to accommodate the differences between the AVR and the Prop. You might be able to minimize the changes by trying to emulate the AVR to a certain extent.
Yes, there are several files that will need severe alterations, but my concept is this..... Maintain as much of the existing source code as possible. When rewriting the necessary files, rewrite the functions and variable names with as many of the existing names as possible. However, in some instances, conversion is a piece of cake, for instance, delay.c and delay.h, have been replaced by #include "simpletools.h", waitcnt(us * value + CNT), and waitcnt(ms * value + CNT), in several locations.
As I see it, my biggest obstacle is matching or emulating the interrupt procedures, because of my lack of knowledge in this area, but I now have some pretty good documentation on the subject.
Maybe I misunderstood your comment about converting to "Propeller lingo".
I certainly could have used different terminology Such as, "Alright now, let's port this macro so that I can understand it"
Comments
My strategy really has not changed much, because I will be starting this new effort, with the same critical core components, which are the DDA filles, the DDA math files, the DDA queue files, the G-Code parser, and the G-Code processor. However, I have also decided to return to the original plan and eliminate conditional compiling. By eliminating the conditional compiling, I will also be eliminating many options offered by the original Teacup firmware. Of course all the options would be nice, but since the original source code is so deeply entrenched in Arduino and AVR support, it would make a complete Propeller port, an extremely daunting task. By porting only the critical components, functional but limited Propeller firmware may be developed for 3D printing. After functional firmware has been developed, other options may be added to enhance the firmware. According to the documentation, ACCELERATION_RAMPING with LOOKAHEAD, appears to be the way to go and that is the type of port that'll be my goal. Additionally, when it comes to parsing the G-Code, I believe the REQUIRE_LINENUMBER and the REQUIRE_CHECKSUM options should be supported, for debugging purposes. As for debugging, there is also the DEBUG option, but this option will initially be unavailable, because the original debug source code will have to be altered to support full duplex serial. However providing DEBUG support should be fairly simple, after the core components are compiling. Until the key components are compiling, all DEBUG source code will be commented out, but left in place, for future reference. When a successful compile is achieved, debugging will then be altered to support full duplex serial and then become available for debugging purposes.
As you have seen in my previous posts, it was originally my intention, to port Teacup into SPIN, but after long and deep consideration, I have decided to port it in C. There are several reasons for choosing C as the programming language, which I will not discuss, because I don't suppose they are important. I am just letting you all know which direction I am heading. So for a large section of the day, I have been cleaning and editing the key files for this project, making the code more legible, by aligning indents, seperating condtions, adding white space, and removing all conditional compilation. When I have all the files the way I want them, I will then begin to edit out the remaining problems until a successful compilation is achieved. This will include making stub functions as Dave suggested and making sure that all variables and constants are clearly defined.
Such are my thoughts.
Bruce
First off, let me say that I was wrong about a couple things. At this point, I am really beginning to see how important the conditional compilations are to this project. Until just recently, I was under the assumption, that the Teacup settings were a set and forget configuration. The deeper I dig into the source code, the more I realize that the configuration settings are sometimes meant to be just temporary settings, and that this firmware was not intended to be simply a set and forget configuration from jump street. However, I am fairly certain that once you have it tuned, you will rarely have to alter the settings. At first, I saw the conditional compilations as a hinderance, but now I am beginning to see them as an asset. By leaving much of the conditional compilation in place, the firmware can be adaptable to many different types of setups, with each configuration being unique to any given particular machine.
So upto this point, I have still been spinning my wheels and going nowhere fast. I have wasted a lot of time and useless effort, just getting a grasp of the process and firmware. And I must say that I always find something new and I must admit that it is a very interesting piece of software.
Anyhow, I got beat up that round and all the previous rounds, but I am not giving up. I just needed to take a few licks, to find out what kind of opponent I was up against. So I will now begin a new round, with conditional compilation.
As for the necessary files, the list has changed to include several more very important files. The new list is as follows:
config.default.h
dda.c
dda.h
dda_lookahead.c
dda_lookahead.h
dda_maths.c
dda_maths.h
dda_queue.c
dda_queue.h
gcode_parse.c
gcode_parse.h
gcode_process.c
gcode_process.h
home.c
home.h
pinio.h
pinio.c
DING DING
EDIT: Hopefully it will all fit.
At first glance, or should I say for quite some time, pinio.h seemed a bit overwhelming, and I was having a bit of trouble understanding, the process, the settings, etc... As I see it now, pinio.h sets up the whole runtime environment, by taking the settings established in the config.h file and applying them to functions throughout the firmware, by defining these funtions according to the settings themselves, within the pinio.h file.
Considering a C port, using SimpleIDE, it appears that pinio.h can be easily altered with the inclusion of simpletools.h. Whereas the READ(s) and WRITE(s) that now exist within pinio.h, could be replaced with functions available from the simpletools library. By replacing these READ(s) and WRITE(s) with simpletools functions, it should define further functions within the firmware that the Teacup frmware needs to operate, thus making a Teacup port actually feasible, without all the additional drudgery of creating stub functions, and writing code that has already been written. Or so I think
Although I have not verified it, I do believe that most of the pins utilized within config.h, are either input or output pins within an Arduino or AVR environment, so there direction does not need to be established, whereas with the Propeller these directions will need to be established, but I have not yet determined the proper location for this. I suppose that if all the pins were being accessed by one cog, everything could be controlled pinio.h. Now I also suppose that cog usage, would also be the determing factor of what should actually be defined in pinio.h, and perhaps there should be files similar to pinio.h for each cog utilized by the necessary pins.
HMMMM....
I must admit, even though I am sure it is obvious, that I know zilch about Arduino and I was wrong when I stated,
Upon further digging, I found READ and WRITE defined within arduino.h, which contains several IO macros. So basically, arduino.h is the setup stage for all communication with the various pins utilized. As many of us already know, mendel.c is starting point of Teacup, because it contains the main function. The io_init function of mendel.c relies heavily upon arduino.h, config.h, and pinio.h, for establishing pins utilized, pin directions, pin states, and setting up functions for easily communicating and interfacing with the various pins.
I mentioned in the previous post that
While I firmly believe the proceeding statement to be true, this will not affect the use of SET_OUTPUT utilized within mendel.c and pinio.h, because it is defined within arduino.h. By altering both arduino.h and pinio.h to match the functions of the simpletools library, I think a very large portion of the Teacup software can remain as it is.
EDIT: It almost appears that only the arduino.h file needs to be modified. Wouldn't that be a hoot
I am now at a point where I believe the main portion of the port will be the altering of the following code to become Propeller friendly:
Source: Teacup firmware - arduino.h
EDIT: I could probably use a little help with this, if anyone is so inclined
EDIT: Here is the funny thing.... And I am sure you will all get a good laugh.... config.h states the following: Source: Teacup firmware - config.h
I read this comment numerous times, but I just did not understand where to begin. After a lot of research and studying of the firmware, now I understand
EDIT: In an effort to provide an easier understanding, I have altered the code above as follows: Source: Teacup firmware - arduino.h
After further examination and considering the unknowns of the macros defined within arduino.h, I am now inclined to believe that a modification of pinio.h would be the easiest alternative for porting. In addition to pinio.h, there are several other locations within the Teacup firmware, where the READ and WRITE functions are utilized, as well as some of the additional functions provided by arduino.h. I do believe a Propeller port would be much easier to understand, if all these existing functions were changed to simpletools.h functions, where they are being used.
EDIT: Although I am uncertain how these alterations will affect the program size, when defined or included in multiple locations.
The _READ macro returns the bit value at its position in the I/O register. If it needs to return 1 or 0 the macro should be appended with "!= 0".
Thanks for the reply and effort.
By the time I got back here I had already written something up, but I am unsure of it.
In the past, I normally just used defines for assigning constant values, so I am unsure if the following would work, because it utilizes functions, but I think it will. Anyhow, I believe something similar to the following is the key to porting this monster.
Most of these calls are made from either mendel.c or pinio.h, with very few exceptions. And providing this code is acceptable, all references of "#include arduino.h" should be changed to "#include PropelledTeacup.h", or completely removed. Additionally, all references to the simulator, avr, or arduino specific code should be obliterated.
EDIT: I will try both of them. I believe your macros would leave a much smaller footprint, because if I am not mistaken, that would only require the include of propeller.h.
EDIT: Additionally, I have discovered that _TOGGLE(IO), _GET_INPUT(IO), and _GET_OUTPUT(IO) are unnecessary.
Additionally, this file is named PropellerizedTeacup.h
As I learn about various aspects of the Teacup firmware and as time passes, my goals of this project have changed significantly, or should I say for the time being.
As mentioned, I know nothing about Arduino, so without spending a bunch of time learning about Arduino or unless someone takes the time to educate me, all I can do is make various assumptions. At this current point of time, I am assuming that the Teacup firmware is a single threaded process, that runs without the benefit 8 cogs, or even two parallel processes, mostly because of my lack of knowledge about Arduino and the lack of evidence throughout the firmware, but I could be wrong.
Anyhow, my current goal is to match the operation of Teacup, without taking advantage of all the Propellers attributes. If I can manage that task, then I will see about altering some code to make better use of the Propeller's resources. However this may change as my efforts develop. Of course there are a few exceptions, such as some name changes for the various files, but most of them will remain the same for easy reference, at least for now. However, right from the start, I will be renaming mendel.c to forger.c, to represent the name of the 3D printer prototype that I am building. If I succeed with this port, I will then be referring to the firmware, as the Forger Firmware. As previously mentioned, and please do not forget, my efforts will be geared towards the controller described within this thread: http://forums.parallax.com/showthread.php/155404-Input-Needed-Combining-Propeller-Proto-Board-Prop-DIP-40-and-ADC-for-3D-Printer. However, I am fairly certain that various configurations may be obtained by altering config.h.
With the assistance of Dave Hein, PropellerizedTeacup.h now exists. This file is intended to replace arduino.h, and this file is responsible for all pin settings and communication with the various IO pins that are utilized. Additionally, PropellerizedTeacup.h should allow for a fair amount of conditional compiling of the Teacup firmware for the Propeller.
As I see it now, the biggest remaining obstacle is the serial interface, which includes DEBUG, and it is intermingled throughout a large portion of the files. Before proceeding any futher, I will try determine what must be done to remove this huge obstacle, but it may not be as big of a problem as I believe it is.
Although I am not 100% certain, I am fairly certain that sermsg.h, sermsg.c, sersendf.h, and sersendf.c, can pretty much remain the way they are, with the following exceptions:
change all references of #include "serial.h" to #include <fdserial.h>
change all references of serial_writechar(uint8_t data) to fdserial_txChar (fdserial *term, int txbyte)
Someone please correct me if I am wrong
EDIT: However I am now thinking that this might be a better alternative
change all references of #include "serial.h" to #include "simpletext.h"
change all references of serial_writechar(uint8_t data) to putChar (char c)
EDIT: This was certainly a case of wishful thinking
EDIT: I just got sersend to output to the SimpleIDE terminal the following: sersendf_P(PSTR("rs N%ld Expected line number %ld\n"), 100, 200);
As I have mentioned in a few of my previous posts, I am now attempting to tackle the serial interface problems. I believe this is probably this biggest problem remaining, besides getting rid of all the interrupt stuff, and I know I will also need help with that to.
Anyhow, I have been attempting to get certain Teacup serial interface files to communicate with the simpletext library, and I have had partial success. Of course, partial success just won't cut the mustard.
In an effort to obtain some help and perhaps gain a little more traction with this project, I have created a SimpleIDE project, which should contain a solution to the serial interface problems associated with the Teacup port. However there are still problems to be resolved, as can be witnessed by the attached image.
Any and all effort that you may be willing to share to make the attached SimpleIDE project bulletproof, will be greatly appreciated.
EDIT: Please note that the following define can be removed from sersendf.h of the attached project, because it is not needed: #define pgm_read_word(x) (*((uint16_t *)(x)))
All of the build warnings from the attached project, appear to be a result of calls made to GET_ARG within sersendf.c
All of the warnings (except improper call within main) that appear during a build can be represented by and verified by the following:
I don't know what the proper fix is just yet, but perhaps when this is resolved, then perhaps the communication issues will be resolved.
As I see it, passing uint16_t and int16_t data types to GET_ARG, is the cause of the warnings generated during the build process, whereas uint32_t and int32_t data types do not generate any warnings at all and pass right on through the build process.
Within sermsg.h, serwrite_uint16(v) and serwrite_int16(v) are defined as follows:
As you can clearly see, these short functions are simply defined by the long functions, and therefore they should be processed exactly the same way, except with different data types sent during the calls.
At this point, I am assuming that these two defines are actually just garbage, and that the uint16_t and int16_t data types should just be passed to the serwrite_uint32 and serwrite_int32 functions in the first place.
I do not understand why it was done this way to provide warnings and code collapse. Either way, I am going to toy around with eliminating the serwrite_uint16(v) and serwrite_int16(v) functions and see what happens.
Don't blame me for the code layout... Mine looks neat
Source: Teacup Firmware - modified by me
I sure was wrong with that statement. The compiler spits out all kinds of warnings, with any kind of formatting, but the code holds up without aborting. As I see it, the compiler really does not like different data types when using stdarg.h, and therefore issues warnings.
I have reconfigured the test program to show how everything works, utilizing sermsg and sersendf, as well as simpletext. With the exception of the warnings, and unless I am missing something, everything appears to be working well.
See the attached archive below.
If there is one thing that I have learned during this attempted port, I learned that there are a lot of different issues to consider. If you make one bad choice, then all your work is for nothing, and you must start all over again, or at least that has been true for most of my choices. Luckily for me, it is not that bad, concerning my last bad choice..
If you have been following along, you will know that I am shooting for an ACCELERATION_RAMPING and a LOOKAHEAD port of the firmware. While both of these choices are good for 3D printing, I don't believe the same holds true for a standard CNC machine. Whereas the ACCELERATION_RAMPING would most likely be beneficial to a standard CNC machine, LOOKAHEAD could be very detrimental, because it joins moves together, to prevent excess oozing of the filament, at the end of a targeted move. In the case of a standard CNC machine, you will not have this oozing problem, and you definitely want to hit the target location. By eliminating all of the conditional compiling for LOOKAHEAD, I have essentially made the movement code useless for a standard CNC machine. However, luckily for me, after doing a little research, I have discovered that the only important files affected are dda.c and dda.h. Considering that I will most likely want to use these files for other projects besides 3D printing, I will now have to edit dda.c and dda.h once again, and leave the LOOKAHEAD conditional compiling in full working order.
While editing these two files are a bit of a pain, I realize that the situation could have been a lot worse.
Porting the files analog.c, heater.c, temp.c, and timer.c, should be a real challenge.
In addition to getting very complicated, I have stumbled upon a major disappointment with the following code:
Source: timer.h
Although it may appear simple, this setting runs deep to the core of the firmware, or so it appears. This setting will affect all of the previously mentioned files, as well as dda_queue.c and dda.c. It appears to me that TICK_TIME has a maximum value of 65535, and if that is true, for simplicities sake, the fastest that I will be able to run the Propeller is 20MHz, but that is assuming a port that utilizes large portions of existing code and existing variables.
I definitely want to take full advantage of the Propeller's speed, but for now, I think I will take the easy road (yea right!), and limit the frequency to 20MHz, and later, when I have a much better understanding of it all, I can attempt to alter the code and make it 80MHz compatible.
EDIT: I just searched all the various configuration files that came with the Teacup firmware, and the highest setting I found for F_CPU was indeed 20MHz, and that was located in config.gen7-v1.1-v1.3.h and config.gen7-v1.4.h
Considering the number of views, I know there is curiousity amongst you.
However I am also curious, as to whether anyone else is digging through the Teacup files.
It sure would be nice to have a fellow collaborator about this time
As I have said earlier, I know nothing about Arduino, but according to the comments left by the author, timer.c utilizes two different timers, one for general activities, and another for clocking the step times, but they also refer to some type of comparator. Anyhow, I will have to do some more research, but I believe I will be setting up a cog for these two timers and do my counting with CTRA and CTRB. I am not sure how the comparator fits in there yet, but.....
babysteps
Source: https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328
I now believe this is source of my clock speed limitation of 65535:
So by rewriting the timer aspect of the code, then perhaps we can achieve
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
All the files that were deeply embedded with Arduino specific code need to be rewritten and added to the project. Fairly large size project.
There is some commented Arduino specific code contained within the project files that needs to be reworked for the Propeller. Medium size project.
Replacing a few minor instances of the Arduino serial interface with the Propeller serial interface. Piece of cake.
For some odd reason, LOOKAHEAD is not communicating with the DDA. Haven't found it yet.
Change all 16 bit frequency limitations to 32 bit. Not sure how hard that will be or how deeply it goes.
All items that need attention will be in comments! The comments will contain a date in the form of //2/25/2015// or //2/25/2015//Bruce//. If you want to look at all the potential problems, just search the documents for Bruce or just a date.
@Dave Hein - I had to alter the macros a little to get it to compile, but your assistance helped greatly. All references of "IO ## _PIN" were changed to simply "IO".
It is not communicating, because it is not compiling. I know this because there is no reference to it in the build status pane, and I also know that it contains errors which should show up in the build status pane. However, I still have not located the problem.
EDIT: I found it. At the top of dda_lookahead.c, make the following change:
FROM:
TO:
EDIT: With a few more dated comments, LOOKAHEAD is now communicating with the DDA
Alright now, let's convert it to Propeller lingo
You are missing the bigger picture.....
This is very similar to the previous macros that you helped me with.....
The whole concept is: User settings are defined in config.h and the various macros throughout Teacup pull in the defines of config.h and set the values where they are needed. By doing it that way, all user settings are located in one header file, so that a person with little or no C/C++ experience, can simply alter the settings in one file to match their machine, and build the project, instead of inserting the values in many different locations, throughout the source code.
EDIT: In fact, it would be nice to keep the user settings out of the firmware entirely, and perhaps do an sd card read of a configuration file and assign the values to variables at startup.
EDIT: Or perhaps, at startup, the firmware would look in various locations for the configuration file, like EEPROM (added with something like the file directive in SPIN), the root directory of the SD card, or even the GCODE file itself. And then I suppose the settings could also be configured over a serial connection.
EDIT: So when the firmware is ready, just burn the EEPROM with the firmware and look for the settings elsewhere.
Maybe I misunderstood your comment about converting to "Propeller lingo". I thought you were asking for suggestions on how to handle the DEFINE_HEATER macro.
My point is that I do not want to change the basic theory of operation. Even though I am basically setting this up for my current project, I also want the firmware to be adaptable for other machines, with simple changes to one file. So instead of definining heaters in the heater source, I want to keep them in the config file.
Yes, there are several files that will need severe alterations, but my concept is this..... Maintain as much of the existing source code as possible. When rewriting the necessary files, rewrite the functions and variable names with as many of the existing names as possible. However, in some instances, conversion is a piece of cake, for instance, delay.c and delay.h, have been replaced by #include "simpletools.h", waitcnt(us * value + CNT), and waitcnt(ms * value + CNT), in several locations.
As I see it, my biggest obstacle is matching or emulating the interrupt procedures, because of my lack of knowledge in this area, but I now have some pretty good documentation on the subject.
I certainly could have used different terminology Such as, "Alright now, let's port this macro so that I can understand it"