RobG 1,892 Posted July 5, 2011 Author Share Posted July 5, 2011 Those are the final versions, the ones I will be using from now on I guess. The C's ease of use (relative ,), and the speed of asm. The first one uses only 50 clock cycles, the second one 83, and the third one between 109 and 123. The first one takes up to 12 bit number and returns 4 digit packed BCD. The second one takes up to 12 bit number and a pointer to char array which is then populated with 4 digit BCD result, MSD in the first element. The third one is just like the second, but it maps digits to ASCII characters and blanks leading zeros (returns space instead of 0.) This one is perfect for use with HD44780 LCD displays. You feed it binary number (might be output from ADC) and you get an array of chars ready to be sent to the LCD. For example, number 1234 will be returned as {"0x31",0x32","0x33","0x34"}, then all you need to do is set the address on the display and send elements one by one. Display will look like "1234." If the number is smaller, 12 for example, leading digits will be blanked {"0x20",0x20","0x31","0x32"} and the display will look like " 12", meaning you don't have to mess around with positioning. First one, binary to packed bcd unsigned int bcd = binaryToPackedBCD(1234); unsigned int binaryToPackedBCD(unsigned int n) { __asm(" clr R14"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" mov R14, R12"); return n; } Second one, binary to array (unpacked) unsigned char bcd[4] = {0,0,0,0}; binaryToUnpackedBCD(1234, bcd); void binaryToUnpackedBCD(unsigned int n, unsigned char * digits) { __asm(" clr R14"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" mov.b R14, 3(R13)"); __asm(" swpb R14"); __asm(" mov.b R14, 1(R13)"); __asm(" rra R14"); __asm(" rra R14"); __asm(" rra R14"); __asm(" rra R14"); __asm(" mov.b R14, 0(R13)"); __asm(" swpb R14"); __asm(" mov.b R14, 2(R13)"); __asm(" and #0x0F0F, 0(R13)"); __asm(" and #0x0F0F, 2(R13)"); return; } Third one, binary to ASCII or HD44780 unsigned char chars[4] = {0,0,0,0}; binaryToASCII(780, chars); void binaryToASCII(unsigned int n, unsigned char * characters) { __asm(" clr R14"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" mov.b R14, 3(R13)"); __asm(" swpb R14"); __asm(" mov.b R14, 1(R13)"); __asm(" rra R14"); __asm(" rra R14"); __asm(" rra R14"); __asm(" rra R14"); __asm(" mov.b R14, 0(R13)"); __asm(" swpb R14"); __asm(" mov.b R14, 2(R13)"); __asm(" and #0x0F0F, 0(R13)"); __asm(" and #0x0F0F, 2(R13)"); __asm(" add.b #0x30, 3(R13)"); __asm(" tst.b 0(R13)"); __asm(" jnz l1"); __asm(" mov.b #0x20, 0(R13)"); __asm(" tst.b 1(R13)"); __asm(" jnz l2"); __asm(" mov.b #0x20, 1(R13)"); __asm(" tst.b 2(R13)"); __asm(" jnz l3"); __asm(" mov.b #0x20, 2(R13)"); __asm(" jmp l4"); __asm("l1:"); __asm(" add.b #0x30, 0(R13)"); __asm("l2:"); __asm(" add.b #0x30, 1(R13)"); __asm("l3:"); __asm(" add.b #0x30, 2(R13)"); __asm("l4:"); return; } oPossum, xpg and timotet 3 Quote Link to post Share on other sites
RobG 1,892 Posted July 7, 2011 Author Share Posted July 7, 2011 To make my last function more usable, I have changed it a little bit and included scale. This will be useful for example when sending ADC output to display. The scale can be from 0-4 (anything >4 will be treated as 4.) Here's how the output will look like on the display: scale 0 scale 1 scale 2 scale 3 scale 4 1234 1234 123.4 12.34 1.234 .1234 567 567 56.7 5.67 0.567 .0567 89 89 8.9 0.89 0.089 .0089 1 1 0.1 0.01 0.001 .0001 0 0 0.0 0.00 0.000 .0000 void binaryToASCIIScale(unsigned int n, unsigned char * digits, unsigned int scale); unsigned char s[5] = {0,0,0,0,0}; binaryToASCIIScale(1234, s, 2); void binaryToASCIIScale(unsigned int n, unsigned char * digits, unsigned int scale) { __asm(" clr R15"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" dadd R15, R15"); __asm(" rla R12"); __asm(" dadd R15, R15"); __asm(" rla R12"); __asm(" dadd R15, R15"); __asm(" rla R12"); __asm(" dadd R15, R15"); __asm(" rla R12"); __asm(" dadd R15, R15"); __asm(" rla R12"); __asm(" dadd R15, R15"); __asm(" rla R12"); __asm(" dadd R15, R15"); __asm(" rla R12"); __asm(" dadd R15, R15"); __asm(" rla R12"); __asm(" dadd R15, R15"); __asm(" rla R12"); __asm(" dadd R15, R15"); __asm(" rla R12"); __asm(" dadd R15, R15"); __asm(" rla R12"); __asm(" dadd R15, R15"); __asm(" mov.b R15, 3(R13)"); __asm(" swpb R15"); __asm(" mov.b R15, 1(R13)"); __asm(" rra R15"); __asm(" rra R15"); __asm(" rra R15"); __asm(" rra R15"); __asm(" mov.b R15, 0(R13)"); __asm(" swpb R15"); __asm(" mov.b R15, 2(R13)"); __asm(" and #0x0F0F, 0(R13)"); __asm(" and #0x0F0F, 2(R13)"); __asm(" add.b #0x30, 3(R13)"); __asm(" tst.b 0(R13)"); __asm(" jnz l10"); __asm(" cmp #3, R14"); __asm(" jge l10"); __asm(" mov.b #0x20, 0(R13)"); __asm(" tst.b 1(R13)"); __asm(" jnz l20"); __asm(" cmp #2, R14"); __asm(" jge l20"); __asm(" mov.b #0x20, 1(R13)"); __asm(" tst.b 2(R13)"); __asm(" jnz l30"); __asm(" cmp #1, R14"); __asm(" jge l30"); __asm(" mov.b #0x20, 2(R13)"); __asm(" jmp l40"); __asm("l10:"); __asm(" add.b #0x30, 0(R13)"); __asm("l20:"); __asm(" add.b #0x30, 1(R13)"); __asm("l30:"); __asm(" add.b #0x30, 2(R13)"); __asm("l40:"); __asm(" tst R14"); __asm(" jz l80"); __asm(" dec R14"); __asm(" mov.b 3(R13), 4(R13)"); __asm(" tst R14"); __asm(" jnz l50"); __asm(" mov.b #0x2E, 3(R13)"); __asm(" jmp l90"); __asm("l50:"); __asm(" dec R14"); __asm(" mov.b 2(R13), 3(R13)"); __asm(" tst R14"); __asm(" jnz l60"); __asm(" mov.b #0x2E, 2(R13)"); __asm(" jmp l90"); __asm("l60:"); __asm(" dec R14"); __asm(" mov.b 1(R13), 2(R13)"); __asm(" tst R14"); __asm(" jnz l70"); __asm(" mov.b #0x2E, 1(R13)"); __asm(" jmp l90"); __asm("l70:"); __asm(" dec R14"); __asm(" mov.b 0(R13), 1(R13)"); __asm(" mov.b #0x2E, 0(R13)"); __asm(" jmp l90"); __asm("l80:"); __asm(" mov.b 3(R13), 4(R13)"); __asm(" mov.b 2(R13), 3(R13)"); __asm(" mov.b 1(R13), 2(R13)"); __asm(" mov.b 0(R13), 1(R13)"); __asm(" mov.b #0x20, 0(R13)"); __asm("l90:"); return; } And asm version of the above: .global binaryToASCIIScale binaryToASCIIScale: clr R15 rla R12 rla R12 rla R12 rla R12 rla R12 dadd R15, R15 rla R12 dadd R15, R15 rla R12 dadd R15, R15 rla R12 dadd R15, R15 rla R12 dadd R15, R15 rla R12 dadd R15, R15 rla R12 dadd R15, R15 rla R12 dadd R15, R15 rla R12 dadd R15, R15 rla R12 dadd R15, R15 rla R12 dadd R15, R15 rla R12 dadd R15, R15 mov.b R15, 3(R13) swpb R15 mov.b R15, 1(R13) rra R15 rra R15 rra R15 rra R15 mov.b R15, 0(R13) swpb R15 mov.b R15, 2(R13) and #0x0F0F, 0(R13) and #0x0F0F, 2(R13) add.b #0x30, 3(R13) tst.b 0(R13) jnz l10 cmp #3, R14 jge l10 mov.b #0x20, 0(R13) tst.b 1(R13) jnz l20 cmp #2, R14 jge l20 mov.b #0x20, 1(R13) tst.b 2(R13) jnz l30 cmp #1, R14 jge l30 mov.b #0x20, 2(R13) jmp l40 l10: add.b #0x30, 0(R13) l20: add.b #0x30, 1(R13) l30: add.b #0x30, 2(R13 l40: tst R14 jz l80 dec R14 mov.b 3(R13), 4(R13) tst R14 jnz l50 mov.b #0x2E, 3(R13) jmp l90 l50: dec R14 mov.b 2(R13), 3(R13) tst R14 jnz l60 mov.b #0x2E, 2(R13) jmp l90 l60: dec R14 mov.b 1(R13), 2(R13) tst R14 jnz l70 mov.b #0x2E, 1(R13) jmp l90 l70: dec R14 mov.b 0(R13), 1(R13) mov.b #0x2E, 0(R13) jmp l90 l80: mov.b 3(R13), 4(R13) mov.b 2(R13), 3(R13) mov.b 1(R13), 2(R13) mov.b 0(R13), 1(R13) mov.b #0x20, 0(R13) l90: ret hvontres and bluehash 2 Quote Link to post Share on other sites
hvontres 22 Posted July 19, 2011 Share Posted July 19, 2011 Here is a version modified for mspgcc. It uses a slightly different calling convention (args are put into R15:R12 from left to right) I tested this on a MSP430G2231. To make my last function more usable, I have changed it a little bit and included scale.This will be useful for example when sending ADC output to display. The scale can be from 0-4 (anything >4 will be treated as 4.) Here's how the output will look like on the display: scale 0 scale 1 scale 2 scale 3 scale 4 1234 1234 123.4 12.34 1.234 .1234 567 567 56.7 5.67 0.567 .0567 89 89 8.9 0.89 0.089 .0089 1 1 0.1 0.01 0.001 .0001 0 0 0.0 0.00 0.000 .0000 void binaryToASCIIScale(unsigned int n, unsigned char * digits, unsigned int scale); unsigned char s[5] = {0,0,0,0,0}; int data=1234; int sc=2; void main (void){ binaryToASCIIScale(data, s, sc); } void binaryToASCIIScale(unsigned int n, unsigned char * digits, unsigned int scale) { __asm(" clr R12"); __asm(" rla R15"); __asm(" rla R15"); __asm(" rla R15"); __asm(" rla R15"); __asm(" rla R15"); __asm(" dadd R12, R12"); __asm(" rla R15"); __asm(" dadd R12, R12"); __asm(" rla R15"); __asm(" dadd R12, R12"); __asm(" rla R15"); __asm(" dadd R12, R12"); __asm(" rla R15"); __asm(" dadd R12, R12"); __asm(" rla R15"); __asm(" dadd R12, R12"); __asm(" rla R15"); __asm(" dadd R12, R12"); __asm(" rla R15"); __asm(" dadd R12, R12"); __asm(" rla R15"); __asm(" dadd R12, R12"); __asm(" rla R15"); __asm(" dadd R12, R12"); __asm(" rla R15"); __asm(" dadd R12, R12"); __asm(" rla R15"); __asm(" dadd R12, R12"); __asm(" mov.b R12, 3(R14)"); __asm(" swpb R12"); __asm(" mov.b R12, 1(R14)"); __asm(" rra R12"); __asm(" rra R12"); __asm(" rra R12"); __asm(" rra R12"); __asm(" mov.b R12, 0(R14)"); __asm(" swpb R12"); __asm(" mov.b R12, 2(R14)"); __asm(" and #0x0F0F, 0(R14)"); __asm(" and #0x0F0F, 2(R14)"); __asm(" add.b #0x30, 3(R14)"); __asm(" tst.b 0(R14)"); __asm(" jnz l10"); __asm(" cmp #3, R13"); __asm(" jge l10"); __asm(" mov.b #0x20, 0(R14)"); __asm(" tst.b 1(R14)"); __asm(" jnz l20"); __asm(" cmp #2, R13"); __asm(" jge l20"); __asm(" mov.b #0x20, 1(R14)"); __asm(" tst.b 2(R14)"); __asm(" jnz l30"); __asm(" cmp #1, R13"); __asm(" jge l30"); __asm(" mov.b #0x20, 2(R14)"); __asm(" jmp l40"); __asm("l10:"); __asm(" add.b #0x30, 0(R14)"); __asm("l20:"); __asm(" add.b #0x30, 1(R14)"); __asm("l30:"); __asm(" add.b #0x30, 2(R14)"); __asm("l40:"); __asm(" tst R13"); __asm(" jz l80"); __asm(" dec R13"); __asm(" mov.b 3(R14), 4(R14)"); __asm(" tst R13"); __asm(" jnz l50"); __asm(" mov.b #0x2E, 3(R14)"); __asm(" jmp l90"); __asm("l50:"); __asm(" dec R13"); __asm(" mov.b 2(R14), 3(R14)"); __asm(" tst R13"); __asm(" jnz l60"); __asm(" mov.b #0x2E, 2(R14)"); __asm(" jmp l90"); __asm("l60:"); __asm(" dec R13"); __asm(" mov.b 1(R14), 2(R14)"); __asm(" tst R13"); __asm(" jnz l70"); __asm(" mov.b #0x2E, 1(R14)"); __asm(" jmp l90"); __asm("l70:"); __asm(" dec R13"); __asm(" mov.b 0(R14), 1(R14)"); __asm(" mov.b #0x2E, 0(R14)"); __asm(" jmp l90"); __asm("l80:"); __asm(" mov.b 3(R14), 4(R14)"); __asm(" mov.b 2(R14), 3(R14)"); __asm(" mov.b 1(R14), 2(R14)"); __asm(" mov.b 0(R14), 1(R14)"); __asm(" mov.b #0x20, 0(R14)"); __asm("l90:"); return; } RobG 1 Quote Link to post Share on other sites
nuetron 64 Posted July 19, 2011 Share Posted July 19, 2011 Hey y'all, did you see this? Ranjit[/url]":1er9xjjb]void tostr(int i,char *str); //Converts Integers to String, useful routine void tostr(int i,char *s) // Convert Interger to String { char *p; p=s; if(i >= 200) p[0]= 2; else if(i >= 100) p[0]= 1; else p[0]= 0; p[2]=i%10; i-=p[2]; i/=10; p[1]=i%10; p[3] = 0; // mark end of string p[2]+=0x30; p[1]+=0x30; p[0]+=0x30; } 'tostr' takes a binary integer (or character) and converts it to a string of chars that get printed on an HD44780. I modified it to suit my application, now it displays four digits instead of three (the highest number is 9999): void PrintStr(char *Text); char foo[4]; void tostr(int i,char *str); //Converts Integers to String, useful routine // These three are used like this: void main (void) { tostr(counter,foo); sendInstruction(0xC0); PrintStr(foo); } a void PrintStr(char *Text) { char *c; c = Text; while ((c != 0) && (*c != 0)) { sendData(*c); c++; } } void tostr(int i,char *s) { // Convert Integer to String char *p; p=s; p[3]=i%10; i-=p[3]; i/=10; p[2]=i%10; i-=p[2]; i/=10; p[1]=i%10; i-=p[1]; i/=10; p[0]=i%10; i-=p[0]; p[4] = 0; // mark end of string p[3]+=0x30; p[2]+=0x30; p[1]+=0x30; p[0]+=0x30; } Feel free to ignore me if this isn't relevant. Quote Link to post Share on other sites
timotet 44 Posted July 28, 2011 Share Posted July 28, 2011 Hey RobG Could you give a small example of how to use the Binary to ASCII code for the noobs like me? :shifty: I am working on a project that uses the TI RTC code. located here: http://focus.ti.com/general/docs/litabs ... r=slaa290a The output for the clock is in BCD and I have not been able to figure out how to convert it. I tried just adding 0x30 to the BCD output but that only works up to 9, so I though this may be the answer. this is from the TI info: "To be easily displayable on an LCD, all variables are encoded in BCD. All variables, except the year, use one byte." The clock is ticking away if only I could display it correctly. thanks Quote Link to post Share on other sites
RobG 1,892 Posted July 28, 2011 Author Share Posted July 28, 2011 Here's what you need to do, you have to get digits from nibbles: int digit = (seconds >> 4) + 0x30; send(digit); digit = (seconds & 0x0F) + 0x30; send(digit); Repeat same for minutes and hours. Basically, all variables are already BCD encoded meaning nibbles are between 0-9, no binary to BCD is necessary. timotet 1 Quote Link to post Share on other sites
oPossum 1,083 Posted July 28, 2011 Share Posted July 28, 2011 send((seconds >> 4) + '0'); send((seconds & 0x0F) + '0'); timotet 1 Quote Link to post Share on other sites
timotet 44 Posted July 28, 2011 Share Posted July 28, 2011 WOW! you guys are quick thanks! Quote Link to post Share on other sites
timotet 44 Posted July 29, 2011 Share Posted July 29, 2011 Ok thanks for the code! RobG I tried yours first and the display is not correct. It is not displaying the numbers its displaying symbols. I think the + 30 is the culprit. opossum I tried yours second and its working correctly. the difference is in the + '0'. I understand that the +30 adds to the hex value that the character is supposed to be right? for the LCD so since the nibble has the proper value do we not need to add the +30. sorry if this is a noob question. Quote Link to post Share on other sites
RobG 1,892 Posted July 29, 2011 Author Share Posted July 29, 2011 I tried yours first and the display is not correct. It is not displaying the numbers its displaying symbols. I think the + 30 is the culprit. It suppose to be 0x30 which is equivalent of char '0' Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.