|
|
View previous topic :: View next topic |
Author |
Message |
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Tue Nov 17, 2020 5:06 pm |
|
|
Bkamen,
this looks beautiful.
Regards,
Samo |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Tue Nov 17, 2020 6:44 pm |
|
|
PrinceNai wrote: | Bkamen,
this looks beautiful.
|
You should see it in UltraEdit with syntax highlighting. :D
Seriously though - thank you.
I'm reluctant to post code because I always look at it wondering if a professional would do it that way.
I usually avoid GOTOs, but I thought at the time it was a rare but nice fit.
As the years go by and I keep writing stuff -- especially Verilog for FPGAs, I've been formatting things a certain way that really helps me make code that's visually coherent in a way that I can quickly check a blob for mistakes.
Kinda weird how that works out.
Thanks again. _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
aldina
Joined: 09 Oct 2009 Posts: 26
|
|
Posted: Wed Nov 18, 2020 11:46 am |
|
|
This drive me crazy....
Code: |
#include <16F18323.h>
#FUSES NOLVP
#FUSES NOWDT
#FUSES RSTOSC_HFINTRC
#FUSES NOCLKOUT
#FUSES BROWNOUT, LPBOR, PUT, BORV27
#FUSES NOPROTECT
#fuses NOEXTOSC
#use delay(internal=32000000)
#pin_select U1TX = PIN_C4
#pin_select U1RX = PIN_C5
#use rs232 (UART1, baud = 9600, ERRORS, RECEIVE_BUFFER=128)
#BYTE OSCCON1 = 0x919 // OSCCON register (pg 37 datasheet)
#BYTE WDTCON = 0x97 // WDTCON (pg 27 datasheet)
#include <stdio.h>
#include <stdlib.h>
//Global Variables
int8 speedk, speed;
int8 Dollar_Sign, Got_Data, gsm_state;
#INT_RDA
void isr_gps(void)
{
// Variables of INT.
unsigned char tmp;
char buffer[10];
int8 next_in;
int8 Character_Counter;
char Nmea_State;
// Inicialise Vars
tmp = 0x00;
Character_Counter = 0;
next_in = 0;
tmp=getc(); // get received char and thus also clear interrupt flag
// ............................................................................
// Process reception through state machine
// Possible data from NMEA module that will be handled is $GPVTG plus data
//
// Actions of this state machine are:
//
// Dollar_Sign = 1; inform MAIN that we have an $
// Got_Data = 1; inform MAIN we have some data to work on
// main is responsible to clear those flags
switch (Nmea_State)
{
// get initial character, '$'
case 0:
{
if(tmp == '$')
{ // we have "$", could be "$GPVTG"
gsm_state = 1; // expecting G
Dollar_Sign = 1; // inform main we have an $
//OUTPUT_HIGH(PIN_C3);
}
else
gsm_state = 0;
break;
}
// ********WE HAVE RECEIVED '$' AS A FIRST CHARACTER ******
// we have "$", expecting G
case 1:
{
if(tmp == 'G') // have "G"
gsm_state = 11; // expecting 'P'
else
gsm_state = 0; // reset state machine
break;
}
// we have "$G", expecting 'P'
case 11:
{
if(tmp == 'P') // expecting 'V'
gsm_state = 12;
else
gsm_state = 0; // error, reset state machine
break;
}
// we have "$GP", expecting 'V'
case 12:
{
if(tmp == 'V' ) // expecting 'T'
gsm_state = 13;
else
gsm_state = 0; // error, reset state machine
break;
}
// we have "$GPV", expecting 'T'
case 13:
{
if(tmp == 'T' ) // we have $GPV so far
gsm_state = 14;
else
gsm_state = 0; // error, reset state machine
break;
}
// we have "$GPVT", expecting 'G'
case 14:
{
if(tmp == 'G' ) // we have $GPVT so far
gsm_state = 15; // and now $GPVTG
else
gsm_state = 0; // error, reset state machine
break;
}
// we have "$GPVTG", now wait for the N
case 15:
{
if(tmp == 'N')
gsm_state = 16;
else
gsm_state = 0; // abort, something went wrong
break;
}
// we have "$GPVTG...N", now wait for the , character to start recording your data
case 16:
{
if(tmp == ',')
{
gsm_state = 17;
Character_Counter = 0;
}
else
{
Character_Counter++; // allow max. x characters before you encounter 'N', otherwise
// you could get stuck here in case of garbled data from the module
if(Character_Counter == 4) // put your number here!!!!
{
gsm_state = 0; // abort, something went wrong
Character_Counter = 0;
next_in = 0;
}
}
break;
}
case 17:
{
if(tmp != '.' || tmp != ',')
{ // Record until received.
buffer[next_in]= tmp; // move received char to the appropriate place in buffer.
++next_in; // increment next_in pointer
if(next_in == 10) // prevent rollover
{
next_in=0;
}
}
else
{
Got_Data = 1; // inform main we have the data
gsm_state = 0; // reset state machine
next_in = 0; // go to beginning of the data buffer
speed = atoi(buffer); // convert buffer data to speed var
}
break;
}
} // switch brace
}
void main()
{
enable_interrupts(INT_RDA);
setup_oscillator(OSC_HFINTRC_32MHZ);
// Configuration of outputs
output_low(PIN_C0);
output_low(PIN_C1);
output_low(PIN_C2);
output_low(PIN_C3);
// Inicialize Vars
speedk = 0;
speed = 0;
Dollar_Sign = 0;
Got_Data = 0;
gsm_state = 0;
while(true)
{
//restart_wdt();
if(speed == 0)
{
OUTPUT_high(PIN_C3);
delay_ms(300);
}
else if(speed >= 15) // 15km/h
{
OUTPUT_low(PIN_C3);
delay_ms(300);
}
}
}
|
I'm using 32MHz now with NOWDT.
I'm only are reading and record data from 'N,' so I'm not recording ',' and transfer with atoi() these data from buffer to an int8 var:
Code: | speed = atoi(buffer);
| I think I can use this var speed in main program to turn HIGH or LOW PIN C3.
But it still always ON like before. Maybe I'm using data not so well, right? Or maybe I'm not read only data I need and can't convert with atoi()
Your example seems so clear for me and it is very similar with my purpose and I can not put my idea running :-(
Thank you for your help again. |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Wed Nov 18, 2020 1:18 pm |
|
|
One thing I saw is the value you put for character_counter, 4. This is too small. The idea is to count the number of characters AFTER you got $GPVTG and before you encounter 'N'. The format of the data is:
$GPVTG,0.00,T,,M,0.00,N,0.00,K,.... That means you have at least 17 characters before you see 'N', so character counter must be higher than that. But you changed the code, so that might not be the issue, because that counter doesn't count what was intended any more. What surely is a problem is this:
Code: |
// Inicialise Vars
tmp = 0x00;
Character_Counter = 0;
next_in = 0;
|
Every time you reach RDA_ISR you set next_in to 0, so I think you only write to the first location of the buffer. All starting values should be declared outside the interrupt. Also the plan with the flags was to only record the data inside ISR and then do the calculations in MAIN and only turn LED's on or off when you get new data. Do you use a debugger, to be able to see what is happening? The contents of the buffer, state variable, next_in and so on? There might also be a problem with NULL (or rather the lack of it) in the buffer. ATOI isn't happy without it at the end of the string. That one I missed in my original code. |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Wed Nov 18, 2020 1:24 pm |
|
|
Also case 15 is wrong. If it doesn't see 'N' as the first received character, it goes straight back to waiting for '$' (gsm_state gets reset to 0). You never reach case 16, even if all else works. |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Wed Nov 18, 2020 4:03 pm |
|
|
Code: |
#include <main.h>
char tmp = 0;
int8 Nmea_State = 0;
int8 gsm_state = 0;
int8 Dollar_Sign = 0;
int8 Character_Counter = 0;
int8 next_in = 0;
#define BUFFER_SIZE 16 //create 16 byte large buffer
char buffer[BUFFER_SIZE];
int8 Got_Data = 0;
#INT_RDA
void RDA_isr(void)
{
tmp=getc(); // get received char and thus also clear interrupt flag
// ............................................................................
// Process reception through state machine
// Possible data from NMEA module that will be handled is $GPVTG plus data
//
// Actions of this state machine are:
//
// Dollar_Sign = 1; inform MAIN that we have an $
// Got_Data = 1; inform MAIN we have some data to work on
// main is responsible to clear those flags
switch (Nmea_State) {
//get initial character, '$'
case 0:{
if(tmp == '$'){ //we have "$", could be "$GPVTG"
gsm_state = 1; //expecting G
output_toggle(PIN_C1); // blink the led every time you get an $
Dollar_Sign = 1; // inform main we have an $
}
else {
gsm_state = 0;
}
break;
}
//********WE HAVE RECEIVED '$' AS A FIRST CHARACTER***************************
// we have "$", expecting G
case 1:{
if (tmp == 'G') //have "G"
gsm_state = 11; //expecting 'P'
else
gsm_state = 0; //reset state machine
break;
}
// we have "$G", expecting 'P'
case 11: {
if(tmp == 'P' ) // expecting 'V'
gsm_state = 12;
else
gsm_state = 0; //error, reset state machine
break;
}
// we have "$GP", expecting 'V'
case 12: {
if(tmp == 'V' ) // expecting 'T'
gsm_state = 13;
else
gsm_state = 0; //error, reset state machine
break;
}
// we have "$GPV", expecting 'T' }
case 13: {
if(tmp == 'T' ) // we have $SGPV so far
gsm_state = 14;
else
gsm_state = 0; //error, reset state machine
break;
}
// we have "$GPVT", expecting 'G' }
case 14: {
if(tmp == 'G' ) { // we have $SGPVT so far
gsm_state = 15; // and now $SGPVTG
}
else
gsm_state = 0; //error, reset state machine
break;
}
// we have "$GPVTG", now wait for the N character to start recording your data
case 15: {
if(tmp == 'N'){
gsm_state = 16;
Character_Counter = 0;
}
else{
Character_Counter++; // allow max. x characters before you encounter 'N', otherwise
// you could get stuck here in case of garbled data from the module
if (Character_Counter == 20){ // 16 or 17 max. needed till you get 'N'
gsm_state = 0; // abort, something went wrong
Character_Counter = 0; // 'N' didn't come in time
next_in = 0;
}
}
break;
}
// don't record ',' in the buffer }
case 16: {
if(tmp == ',' ) { // we have $SGPVT so far
gsm_state = 17; // and now $SGPVTG,
}
else
gsm_state = 0; //error, reset state machine
break;
}
case 17: {
if(tmp != ','){ //Record data until received comma is received
buffer[next_in]= tmp; // move received char to the appropriate place in buffer.
++next_in; // increment next_in pointer
if(next_in == BUFFER_SIZE - 1) { // prevent rollover. Numbering in the buffer begins with 0
next_in = 0;
}
}
else{
Got_Data = 1; // inform main we have the data
gsm_state = 0; // reset state machine
buffer[next_in] = '\n'; // put NULL at the end of the string the buffer for ATOI
next_in = 0; // go to beginning of the data buffer
}
break;
}
} // switch brace
}
void main()
{
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while(TRUE)
{
if(Dollar_Sign){
Dollar_Sign = 0; // clear flag
// do one thing
}
if(Got_Data){
Got_Data = 0; // clear flag
// do another thing
}
}
}
|
This should work. Once again, I can't test it, since I don't have a GPS module here. Please note output_toggle(PIN_C1); in state1. The LED should blink every time you get an '$' over the UART. Move this line to other states, so you can see if you even get there. The code was built for 18f46k22, so you'll need to add pin selects at the beginning and chanhe include main.h to whatever name you use for your project.
I can understand your frustration, by the way. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Nov 18, 2020 5:40 pm |
|
|
You could test it. Program a 2nd PIC to output a NMEA test stream
at a desired interval. Connect it to your first PIC and test. |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Wed Nov 18, 2020 7:00 pm |
|
|
True :-) . Will do it tomorrow. |
|
|
aldina
Joined: 09 Oct 2009 Posts: 26
|
|
Posted: Thu Nov 19, 2020 3:28 am |
|
|
Hi PrinceNai,
I follow your recommends, I use: output_toggle(PIN_C1); to see if I'm receiving the correct data, so I can see I have $, than try the same after receive 'G' in case 11 and nothing, LED not blinks.
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Thu Nov 19, 2020 6:03 am |
|
|
I'm with PCMP about a 'controlled' test setup ! Though another PIC sending NMEA data will work, probably easier to use a PC running, say RealTerm, where you press a key and a 'script' (message) can be sent. This way KNOWN data can be sent and frankly easier to make it happen.
I also wonder if it's 'better' to receive the entire NMEA msg in the ISR, then have main() decode/parse ? Perhaps the 'data' is NOT what you expect. Getting the whole msg, then displaying it, would SHOW you what IS coming into the PIC. Maybe there's a flaw in the ISR decode logic
that would show up if you can SEE the incoming data.
Jay |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Thu Nov 19, 2020 6:36 am |
|
|
Case 11 is a "case" problem. It should look for a capital 'P' :-( . Please change that. I whipped together another board to send out the message every second and will test the reception in the evening. I also added a bigger buffer in the beginning of the ISR to capture all the data that comes in.
Regards,
Samo |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Thu Nov 19, 2020 10:46 am |
|
|
PCM programmer wrote: | You could test it. Program a 2nd PIC to output a NMEA test stream
at a desired interval. Connect it to your first PIC and test. |
That's what I did for my test-bed...
Except I used a PC and wrote something in TCL to just rattle out strings I wanted and then added lots of strings I didn't want normally found in the stream.
Code: |
#!/usr/local/bin/tclsh
#
#
# Commandline Args are:
#
# rate (bit rate) port (comm port)
#
#
set debug "0"
set com(port) "com2"
set com(baud) "9600"
set com(bits) "8"
set com(parity) "n"
set com(stop) "1"
set stringlist {
"\$PMRRC01LR0"
"\$PMRRC041KCMI"
"\$PMRRC042KDEC"
"\$PMRRC043KSPI"
"\$PMRRC0517PN6"
"\$PMRRC0511IP6"
"\$PMRRC0510F:4"
"\$PMRRC0510H@4"
"\$PMRRC051<JV7"
"\$PMRRC0519UW7"
"\$PMRRC0519TR7"
"\$PMRRC0519I>5"
"\$PMRRC0513I>5"
"\$PMRRC0522LR6"
"\$PMRRC0532LR6"
"\$PMRRC0572LR6" }
set stringlist2 {
"\$PMRRC041KSPI"
"\$PMRRC042KSTL"
"\$PMRRC043KCMI"
"\$PMRRC0511JP6"
"\$PMRRC0512LR6"
"\$PMRRC0521JP6"
"\$PMRRC0522LR6"
"\$PMRRC0537PN6"
"\$PMRRC0531IP6"
"\$PMRRC0530F:4"
"\$PMRRC0530H@4"
"\$PMRRC053<JV7"
"\$PMRRC0539UW7"
"\$PMRRC0539TR7"
"\$PMRRC0539I>5"
"\$PMRRC0533I>5"
}
# =========================================================
# Wait for bytes on $chan
#
proc serial_receiver { chan } {
set data ""
if { [gets $chan data] >= 0 } {
puts "<-- $data"
} else { puts -nonewline "" }
if { [eof $chan] } {
puts stderr "Closing $chan"
catch {close $chan}
set done 1
}
}
# ---------------------------------------------------------
# ---------------------------------------------------------
# Main Routine that sets up comport for Reading and then waits
# forever. Exciting, eh?
if { [llength $argv] > 0 } {
foreach arg $argv {
switch -regexp -- $arg {
{^[-]d$} { set debug "1" }
{^[-]d.$} { regexp {^[-][Dd]([\d])$} $arg junk debug }
default {
puts "\nUsage: VHF-Tester.tcl | \[-dn\]"
puts "\t\t\t -dn = debug level n"
puts ""
exit 2
}
}
}
}
if { [ catch { open $com(port) r+ } serial ] } {
if {$debug} {
puts -nonewline "Opening Com Port..."
puts "Hmmm.. something happened... $serial"
exit
}
}
if {$debug} {
puts "Setting Mode..."
}
fconfigure $serial -mode "$com(baud),$com(parity),$com(bits),$com(stop)" \
-blocking 0 -buffersize 500 -buffering full -translation crlf
set item_index "0"
set timeout "0"
set delay_loop "0"
set which "0"
while (1) {
if { !$delay_loop } {
switch -regexp ($which) {
"0" {
puts "--> [lindex $stringlist $item_index] "
puts $serial "[lindex $stringlist $item_index]"
flush $serial
if { $item_index > [llength $stringlist] } {
set which "0"
set item_index "0"
} else {
incr item_index
}
}
"1" {
puts "--> [lindex $stringlist2 $item_index] "
puts $serial "[lindex $stringlist2 $item_index]"
flush $serial
if { $item_index > [llength $stringlist2] } {
set which "0"
set item_index "0"
} else {
incr item_index
}
}
}
set delay_loop "50"
}
if {$delay_loop} {
set delay_loop [expr $delay_loop -1]
}
fileevent $serial readable [ serial_receiver $serial ]
after 1
}
|
_________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Thu Nov 19, 2020 1:16 pm |
|
|
So many stupid mistakes :-( . Anyway, I'm sending this string from my sender board with 19.200 baud: "$GPVTG,360.0,T,348.7,M,000.0,N,123.4,K*34\n"
I tested the sending PIC on a terminal and it does output that.
After correcting one oversight, the following code works. I get 123.4 in the buffer.
Code: |
#include <main.h>
char tmp = 0;
int8 Nmea_State = 0;
int8 Dollar_Sign = 0;
int8 Character_Counter = 0;
int8 next_in = 0;
#define BUFFER_SIZE 8 //create 16 byte large buffer
char buffer[BUFFER_SIZE];
int8 Got_Data = 0;
int8 Test_Buffer_Pointer = 0;
#define Test_Buffer_Size 64
char Test_Buffer[Test_Buffer_Size];
#INT_RDA
void RDA_isr(void)
{
tmp=getc(); // get received char and thus also clear interrupt flag
Test_Buffer[Test_Buffer_Pointer]= tmp; // move received char to the appropriate place in buffer.
++Test_Buffer_Pointer; // increment next_in pointer
if(Test_Buffer_Pointer == Test_Buffer_Size - 1) { // prevent rollover. Numbering in the buffer begins with 0
Test_Buffer_Pointer = 0;
}
// ............................................................................
// Process reception through state machine
// Possible data from NMEA module that will be handled is $GPVTG plus data
//
// Actions of this state machine are:
//
// Dollar_Sign = 1; inform MAIN that we have an $
// Got_Data = 1; inform MAIN we have some data to work on
// main is responsible to clear those flags
switch (Nmea_State) {
//get initial character, '$'
case 0:{
if(tmp == '$'){ //we have "$", could be "$GPVTG"
Nmea_State = 1; //expecting G
output_toggle(PIN_C1); // blink the led every time you get an $
Dollar_Sign = 1; // inform main we have an $
}
else {
Nmea_State = 0;
}
break;
}
//********WE HAVE RECEIVED '$' AS A FIRST CHARACTER***************************
// we have "$", expecting G
case 1:{
if (tmp == 'G') //have "G"
Nmea_State = 11; //expecting 'P'
else{
Nmea_State = 0; //reset state machine
}
break;
}
// we have "$G", expecting 'P'
case 11: {
if(tmp == 'P' ) // expecting 'V'
Nmea_State = 12;
else{
Nmea_State = 0; //error, reset state machine
}
break;
}
// we have "$GP", expecting 'V'
case 12: {
if(tmp == 'V' ) // expecting 'T'
Nmea_State = 13;
else{
Nmea_State = 0; //error, reset state machine
}
break;
}
// we have "$GPV", expecting 'T' }
case 13: {
if(tmp == 'T' ) // we have $SGPV so far
Nmea_State = 14;
else{
Nmea_State = 0; //error, reset state machine
}
break;
}
// we have "$GPVT", expecting 'G' }
case 14: {
if(tmp == 'G' ) { // we have $SGPVT so far
Nmea_State = 15; // and now $SGPVTG
}
else{
Nmea_State = 0; //error, reset state machine
}
break;
}
// we have "$GPVTG", now wait for the N character to start recording your data
case 15: {
if(tmp == 'N'){
Nmea_State = 16;
Character_Counter = 0;
}
else{
Character_Counter++; // allow max. x characters before you encounter 'N', otherwise
// you could get stuck here in case of garbled data from the module
if (Character_Counter == 28){ // 25 or 26 max. needed till you get an 'N'
Nmea_State = 0; // abort, something went wrong
Character_Counter = 0; // 'N' didn't come in time
next_in = 0;
}
}
break;
}
// don't record ',' in the buffer
case 16: {
if(tmp == ',' ) { // now get the data
Nmea_State = 17;
}
else{
Nmea_State = 0; //error, reset state machine
}
break;
}
case 17: {
if(tmp != ','){ //Record data until comma is received
buffer[next_in]= tmp; // move received char to the appropriate place in buffer.
++next_in; // increment next_in pointer
if(next_in == BUFFER_SIZE - 1) { // prevent rollover. Numbering in the buffer begins with 0
next_in = 0;
}
}
else{
buffer[next_in] = '\n'; // put NULL at the end of the string in the buffer for ATOI
next_in = 0; // go to beginning of the data buffer
delay_cycles(1);
Got_Data = 1; // inform main we have the data
Nmea_State = 0; // reset state machine
Test_Buffer_Pointer = 0;
}
break;
}
} // switch brace
}
void main()
{
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
while(TRUE)
{
if(Dollar_Sign){
Dollar_Sign = 0; // clear flag
// do one thing
}
if(Got_Data){
Got_Data = 0; // clear flag
// do another thing
}
} // while true
} // main
|
Now about my mistake. The code was rewritten from an existing GSM project. I changed the name of the switch statement for this, but never the name of the states (gsm_state, Nmea_State). Of course it came only till state 0.
I do have a question for the OP: How do you get your speed out of this info? Is the dot correctly positioned or does it output the data reversed?
Regards,
Samo
Last edited by PrinceNai on Fri Nov 20, 2020 8:00 am; edited 11 times in total |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Thu Nov 19, 2020 1:20 pm |
|
|
This is what I found on the net for that answer:
$GPVTG
Track Made Good and Ground Speed.
eg1. $GPVTG,360.0,T,348.7,M,000.0,N,000.0,K*34
eg2. $GPVTG,054.7,T,034.4,M,005.5,N,010.2,K*48
054.7,T True course made good over ground, degrees
034.4,M Magnetic course made good over ground, degrees
005.5,N Ground speed, N=Knots
010.2,K Ground speed, K=Kilometers per hour
eg3. for NMEA 0183 version 3.00 active the Mode indicator field
is added at the end
$GPVTG,054.7,T,034.4,M,005.5,N,010.2,K,A*25
A Mode indicator (A=Autonomous, D=Differential,
E=Estimated, N=Data not valid)
If this is the correct format for the GPS output you get, you should change the limit of Data_Counter in state 15 to at least 25, otherwise you'll never see a 'N' in case 15. I already edited the code above to the last working one I have. Format of the message I found on the net is already taken into account. Also, if you'll do ATOI on the buffer, you'll only get the decimal representation of the part before the dot.
Regards,
Samo |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|