Jump to content

MIOS_HLP_Dec2BCD


 Share

Recommended Posts

Hello everyone...

I'm trying to convert 12bit decimal numbers to single ascii chars and stumbled over this quite helpful mios function MIOS_HLP_Dec2BCD(unsigned int value)...

However, the numbers generated from MIOS seem to be others than I would expect following the descriptions. My AC-Sim debugger produces the right numbers (I implemented a function that does exactly what I would MIOS expect to do: 12345 => 0x1, 0x23, 0x45 in MIOS_PARAMETER3, -2 and -1):

// from the debug_mios.c file that simulates MIOS

extern void MIOS_HLP_Dec2BCD(unsigned int value) { 
	// decimals to hex (eg 123456 to 0x12, 0x34, 0x56)
	unsigned char a;
	unsigned char b;
	// get 100.000
	a = (unsigned char)(value / 100000);
	b = (unsigned char)((value / 10000) - (a * 10));
	MIOS_PARAMETER3 = (a << 4) + b;
	// get 1.000
	value = value - (a * 100000 + b * 10000);
	a = (unsigned char)(value / 1000);
	b = (unsigned char)((value / 100) - (a * 10));
	MIOS_PARAMETER2 = (a << 4) + b;
	// get 10
	value = value - (a * 1000 + b * 100);
	a = (unsigned char)(value / 10);
	b = (unsigned char)(value - (a * 10));
	MIOS_PARAMETER1 = (a << 4) + b;
}
I tried to debug this with MIOSStudio, but I don't know where to find MIOS_PARAMETER1 to -3 (tried to read RAM from 0x0 to 0x0f, but couldn't get anything back :-[ ) before I have to rewrite an asm-optimized custum function (huh, I'm an ASM-Idiot), I try the forum, maybe anyone knows a hint for me? google has way too much unrelated search resuls and I can't believe it would take so much complicated code to do a dec2BCD-conversion ??? This is the relevant code so far: (input 0..127 => 0..4064 (12bit) => '0'..'4','0','6','4') ...just produces unordered garbage numbers in the range from 0 to 8149
#define NUM2ASCII(num) (num + 0x30)

unsigned char IIC_SPEAKJET_Transmit12bit(unsigned short value) __wparam {
	unsigned char c;
	unsigned char result = 0;
	MIOS_HLP_Dec2BCD(value);
/*  // skipping param3: hundret-thousands
	c = MIOS_PARAMETER3 >> 4;
	if(c > 0) { result = IIC_SPEAKJET_TransmitByte( NUM2ASCII(c) ); }
	// param3: ten-thousands
	c = MIOS_PARAMETER3 & 0x0F;
	if((c > 0) || result) { result = IIC_SPEAKJET_TransmitByte( NUM2ASCII(c) ); }
*/
	// param2: thousands
	c = MIOS_PARAMETER2 >> 4;
	if(c > 0) { result = IIC_SPEAKJET_TransmitByte( NUM2ASCII(c) ); }
	// param2: hundrets
	c = MIOS_PARAMETER2 & 0x0F;
	if((c > 0) || result) { result = IIC_SPEAKJET_TransmitByte( NUM2ASCII(c) ); }
	// param1: tens
	c = MIOS_PARAMETER1 >> 4;
	if((c > 0) || result) { result = IIC_SPEAKJET_TransmitByte( NUM2ASCII(c) ); }
	// param2: ones
	c = MIOS_PARAMETER1 & 0x0F;
	result = IIC_SPEAKJET_TransmitByte( NUM2ASCII(c) );	// also transmit '0'
	return result;
}

void IIC_SPEAKJET_OSCFreq(unsigned char osc, unsigned short value, unsigned char valueIs14bit) __wparam {
	// osc = 1..5, value = 0..16383 or 0..127
	unsigned short value12bit;
	if(valueIs14bit) {
		value12bit = value;
	} else {
		// value is 0..127, SCP_FREQ_MAX is 3999
		value12bit = value << 5;	// 0..4064 (12 bit)
	}
	IIC_SPEAKJET_TransmitStart(0);
	//		write frequency to register
	IIC_SPEAKJET_Transmit12bit(value12bit);
	IIC_SPEAKJET_TransmitByte(SCP_MEMWRT);
	IIC_SPEAKJET_TransmitStop();
}

thanksalot,

Michael ;)

Link to comment
Share on other sites

(I've currently not so much time to test this...)

MIOS uses this function internally within MIOS_LCD_BCD4 and MIOS_LCD_BCD5, therefore I'm sure that it delivers the right results.

But there could be a problem in the C wrapper (maybe the integer value is passed in the wrong way - this can happen depending on the SDCC version you are using)

Best Regards, Thorsten.

Link to comment
Share on other sites

thank you, TK!

I will interspect this (short on time, too ;D ) and report back.

I temporarily fixed this by hardcoding notes-to-frequency-as-single-ASCII-Char output, which I wanted to do anyway, so this is no super-urgent issue anymore;

however I am still interested in finding the cause of this strange behavior, because a seamless 14-bit resolution frequency control would be a nice feature for the speakJet :)

(but no need for you to invest your valueable time in this, I'm sure, I'll find the bugs... and some mates from the SpeakJet thread wanted to post their opinions, too :D )

Cheers,

Michael

Link to comment
Share on other sites

Hi AC.... I've looked this over and there's only one thing I'm not so sure about - the /100000 . Even with TK's tweaked libsdcc, only 16 bit divides are catered for. Have I missed something, or is this algorithm not going to work? Anyway you could get around it by doing a right shift and dividing that... Otherwise therre's our old friend __ASM ;)

Link to comment
Share on other sites

I'm not so sure about - the /100000

(...) Have I missed something,

;) yes :)

... that's only my tweaking code for the debugger. I posted it because it does what I expect MIOS to do... and because the numbers match if I debug it, but it produces just trash if run on the PIC.

The actual application code is in the lower code-box...

:)

Thanks mate!

Link to comment
Share on other sites

Ohhh I understand now sorry....

Man that's a pickle. Whatever is wrong with it, sure is not obvious! I personally would put some code in there to get the app to send the variable's values in sysex strings, so you can see exactly where it falls over...

Link to comment
Share on other sites

Whatever is wrong with it, sure is not obvious!

Hey, no need to say sorry, that's exactly what I wanted to hear in the first run ;D

(I'm always a bit stressed if I post a question, because in 98% of all cases I've been beaten with incredible blindness :) )

It's an 'int' and sdcc says int's are 8-bit only....

hmm, but 8bit are 255 max, which would be a char, right?

...But I feel this is the right direction, think it might have something to do with my unsigned short instead of unsigned int declarations, maybe this has been a bit toooo optimized  :-\

I'm going to interspect this when I'm back again in about two weeks (look up SDCC int/short specs) and report...

Thanks again for your help, stryd! :)

Cheers, Michael

Link to comment
Share on other sites

Hi,

I couldn't leave my fingers from continuing debugging:

MIOSStudio beta7.2 does not support returning values or reading SRAM, so I tried it with beta5.1 which works :D

- When I call [tt]MIOS_HLP_Dec2BCD()[/tt] with the decimal number [tt]255[/tt] in [tt]WREG[/tt] from FunctionBuilder, I see:

[tt]WREG: 55 MIOS_PARAM1: 55 MIOS_PARAM2: 02 MIOS_PARAM3: 00[/tt] (right!, hex)

- When I send the dec number [tt]256[/tt] I get:

[tt]WREG: 00 MIOS_PARAM1: 00 MIOS_PARAM2: 00 MIOS_PARAM3: 00[/tt] (wrong!, hex)

[tt]WREG: 000 MIOS_PARAM1: 000 MIOS_PARAM2: 000 MIOS_PARAM3: 000[/tt] (wrong! dec)

:D ...but I don't know if the 8bit restriction is due to MIOSStudio or a problem in the Wrapper or inside MIOS? :'(

Cheers,

Michael

ps: The outputs of "SRAM Read" from address 0x003 (No.Bytes 0x3) are:

[tt]255 => 3: 40 00 00

256 => 3: 40 02 00[/tt]

which is not what I expect to find at addresses 0x003, 0x004 and 0x005 (MIOS_PARAMETERs)

Link to comment
Share on other sites

ps: The outputs of "SRAM Read" from address 0x003 (No.Bytes 0x3) are:

255 => 3: 40 00 00

256 => 3: 40 02 00

which is not what I expect to find at addresses 0x003, 0x004 and 0x005 (MIOS_PARAMETERs)

this is because another thread has propably overwritten the MIOS_PARAMETER* locations in the meantime...

- When I send the dec number 256 I get:

WREG:  00    MIOS_PARAM1:  00    MIOS_PARAM2:  00    MIOS_PARAM3:  00 (wrong!, hex)

WREG: 000    MIOS_PARAM1: 000    MIOS_PARAM2: 000    MIOS_PARAM3: 000 (wrong! dec)

which MIDI message is returned by the core?

Btw.: in mios_lcd.inc you can find some usage example for the MIOS_HLP_Dec2BCD() function. As mentioned before: if there is a problem, I expect it in the wrapper code (still don't have time to debug this...)

Best Regards, Thorsten.

Link to comment
Share on other sites

Thank you Thorsten!

As I can see from the mios_hlp.inc it all works correct if I would only use it correct! [homer]d'oh![/homer]

If I send 0x00 in WREG (lowByte) and 0x1 as PARAMETER1 (highByte) for 256, I get 0x56, 0x02, 0x00... of course!

I don't want to steal your valueable time, TK (and I cannot proceed with this the next two weeks, either :) ), but maybe one of the ASM-cracks here has an idea about the wrapper-code? Even when I'm sitting in front of the Instruction Set Summary it's all a bit like chinese to me  :-[

The concept should be the same for MIOS_LCD_PrintBCD5: before calling the function, the [tt]unsigned int[/tt] parameter has to be splitted to Low-byte in WREG and High-byte in MIOS_PARAMETER1.

I notice a difference in the wrapper for these two similar functions, but I have no clue what FSR* and PREINC* do... to be honest, I'm not even sure if mios_wrapper.asm is the right place to search for...  :-\:

(I tried to use the lines from BCD5 for the Dec2BCD, but apparently this did not work)

;; copied from mios_wrapper.asm
;; --------------------------------------------------------------------------
.MIOS_HLP_Dec2BCD code
_MIOS_HLP_Dec2BCD
	global	_MIOS_HLP_Dec2BCD

	movwf	MIOS_PARAMETER1
	movff	FSR0L, FSR2L
	movf	PREINC2, W
	goto	MIOS_HLP_Dec2BCD

;; --------------------------------------------------------------------------
.MIOS_LCD_PrintBCD5 code
_MIOS_LCD_PrintBCD5
	global	_MIOS_LCD_PrintBCD5

	movff	FSR0L, FSR2L
	movff	PREINC2, MIOS_PARAMETER1
	goto	MIOS_LCD_PrintBCD5

I know I could simply try the asm code from mios_help.inc, but if there's an error in the wrapper indeed, it would be best If I could fix it there, I think...

thank you all for your comments and help!

cheers,

Michael

Link to comment
Share on other sites

Thought I should mention these words from TK:

Also the compiler version is important, since the parameter passing method is not stable yet. Therefore please only use official releases (no snapshots) which have been tested with the wrapper. The current release is 2.5.0

Can you try it with 2.5.0 so we can be sure it isn't your version causing the problems?

Link to comment
Share on other sites

oh, thanks

Unfortunately it has been a total desaster getting SDCC to work on my mac. I couldn't compile the source and it took me weeks to find some precompiled binary versions...

however, I will test this on my ol' PC with SDCC 2.5.0 when I'm back (just have my PowerBook with me atm.)...

So you think the asm-code in the wrapper is okay?

...because it works with the call to MIOS_LCD_PrintBCD5(unsigned int value) but it does not with MIOS_HLP_Dec2BCD(unsigned int value)... and the asm-code in the wrapper is also different... that's what puzzles me a bit... but as you know I have no clue about ASM...

think I'm going to write a new testing app starting with a blank skeleton, maybe it's my source that got screwed up, after all...)

Cheers,

Michael ,)

Link to comment
Share on other sites

Wrapper header says:

extern unsigned char MIOS_HLP_Dec2BCD(unsigned int value) __wparam;
According to SDCCMan it should behave like this:
void func_wparam(int a) wparam
{
/* WREG hold the lower part of a */
/* the high part of a is stored in FSR2+2 (or +3 for large stack model) */
...
}
But it seems from TK's wrapper it puts the high byte in FSR0L.. I'm not clear on that, maybe TK can clear it up for us? Wrapper ASM says:
	global	_MIOS_HLP_Dec2BCD

	movwf	MIOS_PARAMETER1               //Moves W (the low byte of the 16-bit integer) into MIOS_PARAMETER1 - That ain't right. See below from the MIOS Function Reference
	movff	FSR0L, FSR2L                  //These guys
	movf	PREINC2, W                    //Put the high byte in W. D'oh!
	goto	MIOS_HLP_Dec2BCD
As the Function Reference show's, htat's bcakrawds...;D
MIOS_HLP_Dec2BCD 
FUNCTION MIOS_HLP_Dec2BCD 
DESCRIPTION converts a 16-bit decimal value to BCD 
IN low-byte in WREG
high-byte in MIOS_PARAMETER1 
May I recommend changing the wrapper code to:
	global	_MIOS_HLP_Dec2BCD             //The low byte is already in W

	movff	FSR0L, FSR2L                  //These guys
	movf	PREINC2, MIOS_PARAMETER1      //Put the high byte in MIOS_PARAMETER1. Yay!

	goto	MIOS_HLP_Dec2BCD

Oh yeh and I was misinformed, SDCC does treat int's as 16-bit :)

Link to comment
Share on other sites

Since I stayed up to 1m to figure that out and you just walked off...  ;) ;D

FSR* is a File Select Register, it's used to address a section of the PIC's onboard SRAM.

PREINC* Pre-increments this address before reading the RAM at that address

Scope out 5.4.3 INDIRECT ADDRESSING on Page 69 of the PDF datasheet for the 4620,I reckon it'd make sense to you - C or ASM it's all addressing :)

Link to comment
Share on other sites

hey stryd no hurry :), please don't stay awake just for that (although it's very kind from you!!)

I was about to test this before replying...

(but if you're still awake, you know that the australian team is currently playing against italy at the world soccer cup? :) Your country is playing well!)

I'll check this out with the changes in the wrapper (I also had these thoughts, but my knowledge of asm is so poor I couldn't figure it out...) and report back!

Cheers, Michael

(holding my thumb for the soccaroos... sorry to all Italians :) )

Link to comment
Share on other sites

I think that the way how MIOS_LCD_PrintBCD5 passes the parameters should work. I remember that I tested it with the LCD functions, so I forgot to do the same change with MIOS_HLP_Dec2BCD

The changes were required after a change in the parameter passing between 2.4 snapshot xxx and 2.5.0

Due to such facts, I recomment the usage of 2.5.0 only, I cannot guarantee that it will work with the current snapshot builds

Best Regards, Thorsten.

Link to comment
Share on other sites

Hi TK,

No urgency, but when you have a minute.... Could you explain why the address to the high byte is moved from FSR0 to FSR2, and the FSR2 pointer incremented before reading?

Taking the information from the SDCC manual, I know the data should go into FSR2+2...So why the move from FSR0L? Perhaps that information in the manual is outdated? I was also wondering why you didn't just do PREINC0?

I am convinced that I've missed something here ;) I know you are busy, so although I would love to understand a little better, please only answer if you have the time.

Link to comment
Share on other sites

Hi Stryd_one,

thanks for all your help regarding this issue!

I can't access my mbhp hardware the next days, but I really hope, this can be fixed by the wrapper... if it's SDCC indeed, I'll have to implement an ASM routine, 'cause I don't think I'm going to break my working SDCC setup on the Mac (however, will try on the PC the next weeks to identify the problem, nevertheless)...

and no: the Socceroos did some great games, they were just unlucky this time... it's always sad when a game ends like this with a wrong decision :( They would have deserved the next round...

Cheers to Australia! ;)

Michael

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...