I looked at timer.c and it's full of AVR stuff. It seems like you should just study it, and then write a version of timer.c that is specific to the Prop. It appears that the code sets flags, which are then reset by other parts of the Teacup code, so if your lucky there won't be any concurrency issues. Look at timer_ext.c in the simulator directory to see how it's done for the simulator. However, I wouldn't use this version either since it relies on the C library time functions. You should be able to create much more efficient and compact code if you just rely on the Prop counter for timing information.
I have the clock timer done already, now I only need the step timer.
However, I utilized four new files to accomplish the new timer, which are clock_timer.c, clock_timer.h, time_clock.c, and time_clock.h. By introducing these four new files, I have acquired two new warnings. Any possibility that you could take a peek and tell me how to get rid of them? I am not sure where they are coming in. I have attached a new archive with the four files included.
Whenever you get around to learning Git & Github, be sure to check out integration with VS. It can certainly make life easier if you prefer to avoid command lines.
In timer.c, within the ISR(TIMER1_COMPA_vect) and the void setTimer(uint32_t delay) functions, it almost appears that CNT should be assigned to OCR1A, and then various values would be added to it. At this point, I am just making a comment.
I thought you replaced timer.c by clock_timer.c so you wouldn't need to mess with any AVR stuff. There shouldn't be any reason to set OCR1A to anything.
I'm curious why you merged the code in the routine clock_tick() into the interrupt routine. Why not just call clock_tick from the routine? That way you don't have to change the clock.c file. Also you probably want to use a variable to hold the target count value, otherwise your loop will take slightly longer than TICK_TIME clock cycles. So the routine would look like this:
I thought you replaced timer.c by clock_timer.c so you wouldn't need to mess with any AVR stuff. There shouldn't be any reason to set OCR1A to anything
I have the clock timer done already, now I only need the step timer.
There are two (2) timers in timer.c,
/// comparator B is the system clock, happens every TICK_TIME
ISR(TIMER1_COMPB_vect)
{
/// comparator A is the step timer. It has higher priority then B.
ISR(TIMER1_COMPA_vect)
{
So the routine would look like this:
Not so fast, you are missing the key aspect of that fuction, which is altering the various clock flags, for the different time intervals. First the flags are set, then you call dda_clock().
Also, your code is adding TICK_TIME to clock_counter_10ms. It should add TICK_TIME_MS.
Yep, that was a blunder on my part. I am thankful you caught that. However, I will have to go back and review some of my earlier comments in the thread, because that may be a ket limiting factor in the speed of the firmware.
EDIT: However, the TICK_TIME code should work just fine, because it is only determining 10MS, 250MS, and 1S intervals. In clock_timer.h, TICK_TIME is defined as follows:
/// How often we update our clock.
#define TICK_TIME (2 * ms)
EDIT: On another look, "#define TICK_TIME (2 * ms)". I will have to rework that.
TICK_TIME is the number of clock cycles per tick. TICK_TIME_MS is the number of milli-seconds per tick, which is set to 2 in the Teacup code.
The various clock flags are updated in the clock_tick routine in clock.c.
I noticed the second timer routine is used only if MOTHERBOARD is defined. I'm not sure what the MOTHERBOARD flag is, but it seems to determine how the code interfaces to the 3D printer. I'll take a look at the second timer routine. I think it can be implemented in the same cog as the other timer.
The various clock flags are updated in the clock_tick routine in clock.c.
You are correct. So I need to change the comment of "/// maintain state of the clock flags" to "/// set state of the clock flags".
EDIT: However, clock.c will no longer exist, since it is replaced by time_clock.c
EDIT: The file name was changed due to conflicts with a prop-GCC file named clock.h
Whie it is true, that every portion of this port is important, from my standpoint, there are two portions that are more important than any others. The first being the macros that Dave and I worked on, which converted AVR support to Propeller support for all of the IO pins being utilized. Without that conversion, the port wouldn't even be a possibility. The second most important part of the port, is the portion that I am now working on, which is the conversion of AVR support to Propeller support for generating step pulses. Without the proper step pulses, the firmware will be useless.
For those that may be following along, an understanding of AVR timers is essential to successfully porting this key portion of source code. To help educate myself, I will be using two or more references, but I am adding links to two of the references that I have found most helpful, so that others may also learn and participate in the ensuing discussion.
The knowledge gained from these resources, and perhaps others, will be used to port the following code to the Propeller chip.
EDIT: Additionally, I am also including an archive of the last build. This archive represents the current status of this project and port. At the current point, this project will build without error or warning.
/// initialise timer and enable system clock interrupt.
/// step interrupt is enabled later when we start using it
void timer_init()
{
// no outputs
TCCR1A = 0;
}
/// comparator A is the step timer. It has higher priority then B.
ISR(TIMER1_COMPA_vect)
{
// Check if this is a real step, or just a next_step_time "overflow"
if(next_step_time < 65536)
{
// disable this interrupt. if we set a new timeout, it will be re-enabled when appropriate
TIMSK1 &= ~MASK(OCIE1A);
// stepper tick
queue_step();
return;
}
next_step_time -= 65536;
// similar algorithm as described in setTimer below.
if(next_step_time < 65536)
{
OCR1A = (OCR1A + next_step_time) & 0xFFFF;
}
else if(next_step_time < 75536)
{
OCR1A = (OCR1A - 10000) & 0xFFFF;
next_step_time += 10000;
} // leave OCR1A as it was
}
/*! Specify how long until the step timer should fire.
\param delay in CPU ticks
This enables the step interrupt, but also disables interrupts globally.
So, if you use it from inside the step interrupt, make sure to do so
as late as possible. If you use it from outside the step interrupt,
do a sei() after it to make the interrupt actually fire.
*/
void setTimer(uint32_t delay)
{
uint16_t step_start = 0;
// Assume all steps belong to one move. Within one move the delay is
// from one step to the next one, which should be more or less the same
// as from one step interrupt to the next one. The last step interrupt happend
// at OCR1A, so start delay from there.
step_start = OCR1A;
next_step_time = delay;
// Now we know how long we actually want to delay, so set the timer.
if(next_step_time < 65536)
{
// set the comparator directly to the next real step
OCR1A = (next_step_time + step_start) & 0xFFFF;
}
else if(next_step_time < 75536)
{
// Next comparator interrupt would have to trigger another
// interrupt within a short time (possibly within 1 cycle).
// Avoid the impossible by firing the interrupt earlier.
OCR1A = (step_start - 10000) & 0xFFFF;
next_step_time += 10000;
}
else
{
OCR1A = step_start;
}
// Enable this interrupt, but only do it after disabling
// global interrupts (see above). This will cause push any possible
// timer1a interrupt to the far side of the return, protecting the
// stack from recursively clobbering memory.
TIMSK1 |= MASK(OCIE1A);
}
Source: Teacup Firmware (See post #1 of this thread for licensing information)
Since this is the most appropriate place for this information, I am placing it here.
In reference to our discussion pertaining to F_CPU in the timer thread, there are only six references in the remaining portions of the firmware archived above. Most of these references, with the exception of one, are located within the dda_create function of dda.c With the last remaining reference being used within a define of dda_maths.h.
If these formulas were rewritten, I am certain that F_CPU could equal 80MHz, provided there is no overflow, and at which point, I believe if written properly, CNT could be used for the timer.
dda.c(283):
// changed * 10 to * (F_CPU / 100000) so we can work in cpu_ticks rather than microseconds.
// timer.c setTimer() routine altered for same reason
dda.c(286 - 288):
// changed distance * 6000 .. * F_CPU / 100000 to
// distance * 2400 .. * F_CPU / 40000 so we can move a distance of up to 1800mm without overflowing
uint32_t move_duration = ((distance * 2400) / dda->total_steps) * (F_CPU / 40000);
dda.c(299):
c_limit_calc = ((x_delta_um * 2400L) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_X) << 8;
dda.c(307):
c_limit_calc = ((y_delta_um * 2400L) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_Y) << 8;
dda.c(315):
c_limit_calc = ((z_delta_um * 2400L) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_Z) << 8;
dda.c(323):
c_limit_calc = ((e_delta_um * 2400L) / dda->total_steps * (F_CPU / 40000) / MAXIMUM_FEEDRATE_E) << 8;
dda_maths.h(86):
#define C0 (((uint32_t)((double)F_CPU / sqrt((double)(STEPS_PER_M_X * ACCELERATION / 2000.)))) << 8)
Source: Teacup Firmware (See post #1 of this thread for licensing information)
EDIT: On second thought, there is more to it then that..... SetTimer and that value must also be taken into consideration.
I do believe I have a much better grasp of implementing this timer stuff. I was just letting all that AVR mumbo jumbo stuff scare me so much that I failed to see the obvious, I mean it was staring right at and I never even noticed.
void setTimer(uint32_t delay)
Will you look at that? The delay parameter is type uint32_t This means I should just be able to just add it to CNT Which further means that the Teacup firmware should be able to run at 80MHz
Or at least, such is my belief However I could be wrong
I went outside of the realm of this thread seeking information pertaining to timers. For the sake of completeness, I am adding a link to that discussion
Bruce, here's the teacup coding running in the simulator mode on the Prop. The Prop-specific timer stuff is in simulator/timer_ext.c. I created a 64-bit timer that consists of CNT in the lower 32 bits, and the number of times CNT has wrapped in the upper 32 bits. This can be simplified to just 16 bits, but I implemented the 64-bit counter because the simulator uses the nanosecond version for debug purposes.
The program reads the G-Code info from the serial port. I tried the triangle.gcode data and the program outputs data. I think the extra control characters in the output are for setting the display color, which is ignored in the SimpleIDE terminal. The triangle.gcode data is as follows:
Okay I downloaded it and built it, but... I still have not figure out the proper way to send data through SimpleIDE. Do you just paste it to the terminal?
As mentioned in the previous post, the program is currently too large by 1656 bytes, and without a doubt, it will need to have extra code added, for heater maintenance. In addition, if the program is run from a serial port, this will also increase program size.
In this projects current status (archived below), DEBUG, LOOKAHEAD, and GCODE_SD are enabled in the config.h file. There are two new warnings, in addition to the build error.
By simply disabling LOOKAHEAD, the program will fit, however, I consider LOOKAHEAD a necessity.
Even though this program currently unusable, I believe it is very close to being fully fucntional. As I see it, this program is at the bare minimum to becoming a nice piece of firmware, and by removing any existing code, the firmware will be severely hampered.
1) Is there any way to further optimize the existing code, to cut down the size?
2) In addition to the SD card, which I do not want to use to solve this problem, I also have 4MB of flash memory and 128KB of SRAM available. How can I use these resources to overcome this problem.
Anyhow here is the archive (not working).
####WARNING######
If you decide to work on this project, please ensure that you set the proper IO pins in config.h!!!!!!!!!!!!!!!!!!!!!!!!!!!
Bruce, I found a problem in my conversion from 80MHz cycles to nano-second cycles. I divided by 12.5 instead of multiplying times 12.5. The corrected timer_ext.c is attached below along with a modified simulator.c. I turned off the debug prints, and moved the definitions for DEFAULT_TIME_SCALE, verbose, trace_gcode and trace_pos to the beginning of simulator.c. If DEFAULT_TIME_SCALE is 0 the program will run as fast as it can. Otherwise the program will run at 1/DEFAULT_TIME_SCALE times real-time speed.
The code in timer_ext.c runs in a polling mode, where it must be called periodically from the rest of the teacup code. This done by calling sim_time_warp, which is called from the clock function. The advantage to using the polling mode is that the code is single threaded, and runs on one cog. If this isn't fast enough then the code in timer_ext.c would need to run in a separate cog.
BTW, I enter data just by typing it in. Eventually you will either need to read a file or use a serial port. Reading a file will probably not fit in CMM mode, and you would need to go with XMMC mode. If you don't use files you can remove the file-related code and save some memory.
and reading a GCODE file from the sd card, we now have terminal output I must admit it is not working properly, but hey, that is what debug is for
####WARNING######
If you decide to run this project, please ensure that you set the proper IO pins in config.h!!!!!!!!!!!!!!!!!!!!!!!!!!!
Project archive attached below. I am also including a very small GCODE file. Some of the M codes within this file are not supported by Forger. A quick list thrown together shows support for the following codes:
I have been taking it easy for the past couple of days, but today, I will be diving in deep once again. I will be seeking out problems that will prevent this firmware from working.
T o assist me during the debugging process, I will be altering the GCODE test file that I attached above, and after each G1 command, I will be entering a M114 command. This particular command, instructs Forger to report it's current physical position, or in this case, theorhetical physical position. I have not altered the file yet, but when I do, I will amend and attach it to this post.
As mentioned above, Teacup will not fit into the hub, without disabling LOOKAHEAD. I have decided to move ahead with this project, by resolving other errors, which prevent this firmware from working. When I start getting expected results, from the debugging process, indicating that the firmwarm is functional, then I will attempt to resolve the LOOKAHEAD problem.
EDIT: Here is the altered GCODE file that I mentioned above, which includes the M114 commands. It now spits out more data, as intended.
I started the day with good intentions, but as I tried to decipher the terminal output, I became a little flustered, because the output was a mess. So I decided to rewrite portions of the debugging code, so that it would be easier to understand. The archive below contains the results of this endeavor. It is definitely much more comprehendable, and definitely much easier to read.
With the following configuration set in config.h:
LOOKAHEAD disabled
DEBUG enabled
GCODE_SD enabled
and with the debug flags now set in the main function as follows:
I do believe there is a problem with the dda_create function, in fact I know there is one at least, and it is not my fault
If you look at the second DEBUG print command, there are references to a DDA pointer named endpoint. The actual ENDPOINT for creating this DDA, is contained within the "target" parameter of dda_create. And the "dda" parameter of dda_create, is a pointer to a DDA structure, passed from the queue, and the associated values from the "target" parameter are intended to fill the "dda" values for the queue. The first reference to DEBUG is what the second reference to DEBUG should actually look like, or should I say that I am 99.99% positive.
EDIT: Try adding that first debug to the source code and see the output from that
Comments
I have the clock timer done already, now I only need the step timer.
However, I utilized four new files to accomplish the new timer, which are clock_timer.c, clock_timer.h, time_clock.c, and time_clock.h. By introducing these four new files, I have acquired two new warnings. Any possibility that you could take a peek and tell me how to get rid of them? I am not sure where they are coming in. I have attached a new archive with the four files included.
LOL... I don't know how I missed that obvious error, when it was staring right at me A second set of eyes is always a wonderful thing.
I do all of my editing in VS, within a stripped down MFC project, so naturally when I create new source files, they always have the *.cpp extension.
Good catch Dave and thanks for taking a peek.
Bruce
Whenever you get around to learning Git & Github, be sure to check out integration with VS. It can certainly make life easier if you prefer to avoid command lines.
I mean, every line of their source code is a command line. Of sorts.
What's the problem?
I'm curious why you merged the code in the routine clock_tick() into the interrupt routine. Why not just call clock_tick from the routine? That way you don't have to change the clock.c file. Also you probably want to use a variable to hold the target count value, otherwise your loop will take slightly longer than TICK_TIME clock cycles. So the routine would look like this: Also, your code is adding TICK_TIME to clock_counter_10ms. It should add TICK_TIME_MS.
There are two (2) timers in timer.c,
Not so fast, you are missing the key aspect of that fuction, which is altering the various clock flags, for the different time intervals. First the flags are set, then you call dda_clock().
Yep, that was a blunder on my part. I am thankful you caught that. However, I will have to go back and review some of my earlier comments in the thread, because that may be a ket limiting factor in the speed of the firmware.
EDIT: However, the TICK_TIME code should work just fine, because it is only determining 10MS, 250MS, and 1S intervals. In clock_timer.h, TICK_TIME is defined as follows:
EDIT: On another look, "#define TICK_TIME (2 * ms)". I will have to rework that.
And the #define in clock_timer.h should look like this:
The various clock flags are updated in the clock_tick routine in clock.c.
I noticed the second timer routine is used only if MOTHERBOARD is defined. I'm not sure what the MOTHERBOARD flag is, but it seems to determine how the code interfaces to the 3D printer. I'll take a look at the second timer routine. I think it can be implemented in the same cog as the other timer.
TICK_TIME is what I say it is And I say it is an incrementor of 1. Representing 1 MS.
The MOTHERBOARD is the various AVR boards that can be utilized.
You are correct. So I need to change the comment of "/// maintain state of the clock flags" to "/// set state of the clock flags".
EDIT: However, clock.c will no longer exist, since it is replaced by time_clock.c
EDIT: The file name was changed due to conflicts with a prop-GCC file named clock.h
For those that may be following along, an understanding of AVR timers is essential to successfully porting this key portion of source code. To help educate myself, I will be using two or more references, but I am adding links to two of the references that I have found most helpful, so that others may also learn and participate in the ensuing discussion.
AVR130: Setup and Use the AVR® Timers - http://www.atmel.com/Images/doc2505.pdf
COMMON TIMER/COUNTER THEORY - https://sites.google.com/site/qeewiki/books/avr-guide/common-timer-theory
The knowledge gained from these resources, and perhaps others, will be used to port the following code to the Propeller chip.
EDIT: Additionally, I am also including an archive of the last build. This archive represents the current status of this project and port. At the current point, this project will build without error or warning.
Source: Teacup Firmware (See post #1 of this thread for licensing information)
Since this is the most appropriate place for this information, I am placing it here.
In reference to our discussion pertaining to F_CPU in the timer thread, there are only six references in the remaining portions of the firmware archived above. Most of these references, with the exception of one, are located within the dda_create function of dda.c With the last remaining reference being used within a define of dda_maths.h.
If these formulas were rewritten, I am certain that F_CPU could equal 80MHz, provided there is no overflow, and at which point, I believe if written properly, CNT could be used for the timer.
Source: Teacup Firmware (See post #1 of this thread for licensing information)
EDIT: On second thought, there is more to it then that..... SetTimer and that value must also be taken into consideration.
If you get a chance, I would appreciate it, if you could explain this a little more in depth.
I do believe I have a much better grasp of implementing this timer stuff. I was just letting all that AVR mumbo jumbo stuff scare me so much that I failed to see the obvious, I mean it was staring right at and I never even noticed.
void setTimer(uint32_t delay)
Will you look at that? The delay parameter is type uint32_t This means I should just be able to just add it to CNT Which further means that the Teacup firmware should be able to run at 80MHz
Or at least, such is my belief However I could be wrong
I went outside of the realm of this thread seeking information pertaining to timers. For the sake of completeness, I am adding a link to that discussion
http://forums.parallax.com/showthread.php/160416-Duplicating-A-16-bit-Timer-At-16MHz
The program reads the G-Code info from the serial port. I tried the triangle.gcode data and the program outputs data. I think the extra control characters in the output are for setting the display color, which is ignored in the SimpleIDE terminal. The triangle.gcode data is as follows:
Okay I downloaded it and built it, but... I still have not figure out the proper way to send data through SimpleIDE. Do you just paste it to the terminal?
EDIT: 64-bit timer interesting.
I am not saying that this will definitely work at 80MHz, but I think it will.
Source
Header
With the intended main portion uncommented, and DEBUG and LOOKAHEAD enabled, there is hub ram overflow.
In this projects current status (archived below), DEBUG, LOOKAHEAD, and GCODE_SD are enabled in the config.h file. There are two new warnings, in addition to the build error.
By simply disabling LOOKAHEAD, the program will fit, however, I consider LOOKAHEAD a necessity.
Even though this program currently unusable, I believe it is very close to being fully fucntional. As I see it, this program is at the bare minimum to becoming a nice piece of firmware, and by removing any existing code, the firmware will be severely hampered.
1) Is there any way to further optimize the existing code, to cut down the size?
2) In addition to the SD card, which I do not want to use to solve this problem, I also have 4MB of flash memory and 128KB of SRAM available. How can I use these resources to overcome this problem.
Anyhow here is the archive (not working).
####WARNING######
If you decide to work on this project, please ensure that you set the proper IO pins in config.h!!!!!!!!!!!!!!!!!!!!!!!!!!!
The code in timer_ext.c runs in a polling mode, where it must be called periodically from the rest of the teacup code. This done by calling sim_time_warp, which is called from the clock function. The advantage to using the polling mode is that the code is single threaded, and runs on one cog. If this isn't fast enough then the code in timer_ext.c would need to run in a separate cog.
BTW, I enter data just by typing it in. Eventually you will either need to read a file or use a serial port. Reading a file will probably not fit in CMM mode, and you would need to go with XMMC mode. If you don't use files you can remove the file-related code and save some memory.
LOOKAHEAD disabled
DEBUG enabled
GCODE_SD enabled
and with the debug flags now set in the main function as follows:
and reading a GCODE file from the sd card, we now have terminal output I must admit it is not working properly, but hey, that is what debug is for
####WARNING######
If you decide to run this project, please ensure that you set the proper IO pins in config.h!!!!!!!!!!!!!!!!!!!!!!!!!!!
Project archive attached below. I am also including a very small GCODE file. Some of the M codes within this file are not supported by Forger. A quick list thrown together shows support for the following codes:
T o assist me during the debugging process, I will be altering the GCODE test file that I attached above, and after each G1 command, I will be entering a M114 command. This particular command, instructs Forger to report it's current physical position, or in this case, theorhetical physical position. I have not altered the file yet, but when I do, I will amend and attach it to this post.
As mentioned above, Teacup will not fit into the hub, without disabling LOOKAHEAD. I have decided to move ahead with this project, by resolving other errors, which prevent this firmware from working. When I start getting expected results, from the debugging process, indicating that the firmwarm is functional, then I will attempt to resolve the LOOKAHEAD problem.
EDIT: Here is the altered GCODE file that I mentioned above, which includes the M114 commands. It now spits out more data, as intended.
I started the day with good intentions, but as I tried to decipher the terminal output, I became a little flustered, because the output was a mess. So I decided to rewrite portions of the debugging code, so that it would be easier to understand. The archive below contains the results of this endeavor. It is definitely much more comprehendable, and definitely much easier to read.
With the following configuration set in config.h:
LOOKAHEAD disabled
DEBUG enabled
GCODE_SD enabled
and with the debug flags now set in the main function as follows:
and reading a GCODE file from the sd card, we now have much better terminal output.
####WARNING######
If you decide to run this project, please ensure that you set the proper IO pins in config.h!!!!!!!!!!!!!!!!!!!!!!!!!!!
Additionally, I am also including a different GCODE file for debugging purposes, with the empty lines, comments, and the unsupported M codes removed.
If you look at the second DEBUG print command, there are references to a DDA pointer named endpoint. The actual ENDPOINT for creating this DDA, is contained within the "target" parameter of dda_create. And the "dda" parameter of dda_create, is a pointer to a DDA structure, passed from the queue, and the associated values from the "target" parameter are intended to fill the "dda" values for the queue. The first reference to DEBUG is what the second reference to DEBUG should actually look like, or should I say that I am 99.99% positive.
EDIT: Try adding that first debug to the source code and see the output from that
Source: Teacup Firmware