Qbasicnews.com
October 18, 2018, 02:36:08 PM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: Back to Qbasicnews.com | QB Online Help | FAQ | Chat | All Basic Code | QB Knowledge Base
 
   Home   Help Search Login Register  
Pages: [1]
  Print  
Author Topic: Incrementing time represented as NBCD format  (Read 8971 times)
Blitz
I hold this place together
*****
Posts: 853



WWW
« on: December 05, 2006, 12:23:37 PM »

NBCD stands for Natural Binary Coded Decimal and basically means that you  store decimal numbers as you naturally would on paper, except as binary. So what does this mean? It means you use 4 bits to store one number, 0-9. And store them as the ordinary decimal positioning system. So the hexdecimal number 0x3459 stands for the decimal number 3459 and not what it actually means in binary (which is 13401). In this case we're storing time as minutes and seconds in the NBCD format. For example, 0x4712 means 47 minutes and 12 seconds. So the challenge is to write the most elegant code (in which ever language prefer) you can to increment an integer representing time (only minutes and seconds). You have to makes sure that 0x5959 wraps back to 0 once incremented. Challenge closes in exactly one week.

Good luck Smiley
Logged

oship me and i will give you lots of guurrls and beeea
1000101
Ancient Guru
****
Posts: 519



WWW
« Reply #1 on: December 05, 2006, 04:28:35 PM »

FreeBasic code (tested with Win32 CVS Dec 5, 2006)

Code:
#Define HexPad( Number, Padding )   ( Right( String( Padding, "0" ) & Hex( Number ), Padding ) )

Type sTime Field = 1
   
   As uByte   Seconds, Minutes
   
End Type

Sub Inc( Byval pByte As uByte Ptr )
   
   *pByte += 1
   If ( ( *pByte And &H0F ) = &H0A ) Then *pByte += ( &H10 - &H0A )
   
End Sub


Sub IncTime( Byval pTime As sTime Ptr )
   
   Inc( @pTime->Seconds )
   If ( pTime->Seconds = &H60 ) Then
      pTime->Seconds = &H00
      Inc( @pTime->Minutes )
      If ( pTime->Minutes = &H60 ) Then pTime->Minutes = &H00
   End If
   
End Sub

Sub DisplayTime( Byval pTime As sTime Ptr )
   
   Dim As uByte   Seconds = ( ( pTime->Seconds Shr 4 ) * 10 ) + ( pTime->Seconds And &H0F )
   Dim As uByte   Minutes = ( ( pTime->Minutes Shr 4 ) * 10 ) + ( pTime->Minutes And &H0F )
   
   Print Using "##:##   0x"; Minutes; Seconds;
   Print HexPad( *cPtr( uShort Ptr, pTime ), 4 )
   
End Sub


Dim As sTime   Clock


DisplayTime( @Clock )
For X As Integer = 1 to 60 * 60
   
   IncTime( @Clock )
   DisplayTime( @Clock )
   
Next

Sleep
End
Logged

Life is like a box of chocolates', hrm, WTF, no it isn't, more like, 'life is like a steaming pile of horse crap.'
yetifoot
Ancient Guru
****
Posts: 575



« Reply #2 on: December 05, 2006, 06:30:54 PM »

Thats a pretty nice solution by 1000101 there, I would have done it a similar way, but in order to have something to show, I decided to do it the following way.

Again FreeBASIC,

Code:
Function inc_nbcd_timestamp(ByVal timestamp As Integer) As Integer

  timestamp += 1
  timestamp += Abs((timestamp AND &H000F) = &H000A) * &H0006
  timestamp += Abs((timestamp AND &H00F0) = &H0060) * &H00A0
  timestamp += Abs((timestamp AND &H0F00) = &H0A00) * &H0600
  timestamp += Abs((timestamp AND &HF000) = &H6000) * &HA000
  timestamp AND= &HFFFF
 
  Function = timestamp
   
End Function

' JUST SOME TESTING OUTPUT
Dim ts As Integer
Cls
ts = &H5805
For i As Integer = 0 To (60 * 2)
  Locate 1, 1
  ts = inc_nbcd_timestamp(ts)
  Print "0x" + Hex(ts, 4)
  Sleep 150
Next i
Logged

EVEN MEN OF STEEL RUST.
Blitz
I hold this place together
*****
Posts: 853



WWW
« Reply #3 on: December 05, 2006, 07:18:55 PM »

Here's my best shot

Code:
function nbcdTimeIncr ( byval t as integer ) as integer
    t1 = t + &ha6a7
    m1 = t  and &h11110
    m2 = t1 and &h11110
   
    nbcdTimeIncr =  t1 - ((((not (m1 xor m2)) and &h11110) shr 4)*&hf and &ha6a6)
end function


Add AND &hffff if you care that the upper 16 bits are zero or not.
Logged

oship me and i will give you lots of guurrls and beeea
yetifoot
Ancient Guru
****
Posts: 575



« Reply #4 on: December 06, 2006, 12:34:50 AM »

Very interesting, I'm still trying to understand exactly how it works, but I think I'm getting there.

I managed to spot a couple of reductions:

Code:
function inc_nbcd_timestamp ( byval t as integer ) as integer

  dim as integer t1
 
    t1 = t + &HA6A7
       
    function =  t1 - (((((t EQV t1) AND &H11110) shr 4) * &HF) AND &HA6A6)
   
end function
Logged

EVEN MEN OF STEEL RUST.
LooseCaboose
I hold this place together
*****
Posts: 981



« Reply #5 on: December 06, 2006, 04:31:47 AM »

Its easy in Ada:
Code:

procedure add is
  type time is mod 60;
  secs : time := 0;
  mins : time := 0;

begin
  secs := secs + 1;
  if secs = 0 then
    mins := mins + 1;
  end if;
end add;
Logged

esus saves.... Passes to Moses, shoots, he scores!
Dio
I hold this place together
*****
Posts: 874



« Reply #6 on: December 06, 2006, 05:03:51 AM »

i think i misunderstood.

Code:
? mid$(time$,4,2)+right$(time$,2):sleep
Logged

quote="whitetiger0990"]whitetiger is.. WHITE POWER!!! [/quote]
Here
Blitz
I hold this place together
*****
Posts: 853



WWW
« Reply #7 on: December 06, 2006, 09:02:43 AM »

Loose, that's nice. Though that's not really in the nbcd format is it?
Dio, i think you missunderstood. It's not a matter of getting the time as a string.

yetifoot, ic. Didn't know eqv was defined as exactly that. I didn't actually write it in FB. It was originally in assembler. It works by incrementing the number by one, then adding the correct bits so that the numbers which has gone past past 9 and 6 overflow to the next number and wrap around.
Logged

oship me and i will give you lots of guurrls and beeea
yetifoot
Ancient Guru
****
Posts: 575



« Reply #8 on: December 06, 2006, 05:22:11 PM »

I had a play around in assembler too, i thought the BCD functions might be useful, DAA in particular, using some carry trickery. I was hoping to get a code in only 4 or 5 instructions, but the best I could do was 11 including the moves to/from timestamp, and that wasn't using the x86 BCD instructions at all, it was just a quick reworking based on your code,
Logged

EVEN MEN OF STEEL RUST.
LooseCaboose
I hold this place together
*****
Posts: 981



« Reply #9 on: December 06, 2006, 05:39:42 PM »

Quote from: "Blitz"

Loose, that's nice. Though that's not really in the nbcd format is it?

Depends on the Ada compiler I guess ;-). I could create a record subtype that has both the minutes and seconds inside, but there is no guarantee the compiler would allocate 16 contiguous bits for it (it probably wouldn't). Ada is quite nice for somethings, but utterly horrid for others.

I played around with a bit shifty solution, but yours is pretty tough to beat ;-).
Logged

esus saves.... Passes to Moses, shoots, he scores!
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.21 | SMF © 2015, Simple Machines Valid XHTML 1.0! Valid CSS!