; Packed Binary Coded Decimal Simulation
; written by Teresa Carrigan, 2004

globals [ from-number save-from-number BCD-number start-x praise myDigits doneyet? 
          number-of-digits step current-bit last-invert from-list to-list ]
breeds [digit from-digit]
patches-own [ name ]
digit-own [ state ]

;  runs setup when program is first loaded
to startup
  setup
end

;  initializes variables
to setup
  locals [ n these-bits]
  ca
  set praise [ "You got it!" "Right!" "Correct" "Awesome!" "Perfect!" ]
  populate-from-list
  populate-to-list
  set myDigits [ "0" "1" ]
  set from-number ""
  set BCD-number ""
  set number-of-digits 2 + random 8

  ;  make a random decimal number
  repeat number-of-digits
    [ set from-number (word from-number random 10) ]
  set from-number (random-one-of [ "-" "+"] + from-number )
  set save-from-number from-number
  
;    create explanation bars at top and bottom
    ask patches with [ pycor < -25 or pycor > 25]
        [ set pcolor blue ]
    ask patch-at 25 34
      [ set plabel "Packed Binary Coded Decimal Encoding" 
        set plabel-color white
        set name -1
      ]
    ask patch-at 25 28
      [ set plabel "number here"
        set plabel-color white
        set name -2
      ]
    ask patch-at 65 -30
        [ set plabel ""
          set plabel-color white
          set name 1
        ]
    ask patch-at 65 -35
        [ set plabel "" 
          set name 2
        ]
    
    explain -2 "Decimal number to be stored: " + add-commas from-number
    set step 1
    set doneyet? false
    set last-invert "-"
end

to restart
  ask patches with [ pycor >= -25 and pycor <= 25]
    [ set pcolor black 
      set plabel ""
      set name ""
    ]
  ask patches with [ pycor < -25 ]
    [ set plabel "" ]
  ask digit [ die ]
  ask from-digit [die]
  set from-number save-from-number
  set BCD-number ""
  explain -2 "Decimal number to be stored: " + add-commas from-number
  set step 1
  set doneyet? false
end

to explain [ which what ]
  ask patches with [ name = which ]
    [  set plabel what ]
end

to populate-to-list
  locals [ current ]
  set to-list [ "1100" "1101" "1111" "0000" ]
  set current "0000"
  while [ current != "1001" ]
    [ set current (get-next current) 
      set to-list lput current to-list 
    ]
end

to-report get-next [ current ]
  locals [ here-x addend carry total this-digit this-add result ]
  set here-x 3
  set addend "0001"
  set carry 0
  set result ""
  repeat 4
    [  set this-digit read-from-string item here-x current
       set this-add read-from-string item here-x addend
       set total carry + this-digit + this-add
       set carry 0
       if total > 1
         [  set total total - 2
            set carry 1
         ]
       set result (word total result)
       set here-x (here-x - 1)
    ]
  report result   
end

to populate-from-list
  locals [ current ]
  set from-list [ "+" "-" " " "0" ]
  set current 0
  repeat 9
    [ set current (current + 1) 
      set from-list lput (word "" current) from-list 
    ]
  
end

to-report lookup [ what ]
  locals [  n]
  set n position what from-list
  report item n to-list
end


to step1
  locals [ here-x here-y offset]
  explain 1 "First we separate the characters of the decimal number."
  set here-x 70
  set here-y 15
  set offset 15
  ;  make a turtle for each digit
  repeat (number-of-digits + 1) [
    cct-digit 1
      [
        setxy here-x here-y
        set color black
        set label-color white
        set label last from-number
        set from-number but-last from-number
      ]
     set here-x (here-x - offset)
     wait slow-motion
  ]
 set step (step + 1)
end


to step3
  locals [ current-from current-to ]
  explain 1 "Next we convert each character to its BCD nibble."
  ask digit
    [  split who ]
  ask digit
    [  set heading 180
       repeat 15
          [  fd 1
             wait slow-motion
          ]
    ]
  set step (step + 1)
end

to split [ me ]
  locals [  numsteps what horiz vert ]
  set what label-of random-one-of digit with [ who = me ]
  set horiz xcor-of random-one-of digit with [ who = me ]
  set vert ycor-of random-one-of digit with [ who = me ]
  hatch 1 [
            set label lookup what
            set label-color yellow
        ]
    
  ask digit with [ who = me ]
    [ set breed from-digit  ]
end


to step2
  locals [ here-x here-y offset med-slow flag n]
  set med-slow slow-motion / 5
  set offset 15
  explain 1 "Move the sign to the right end."
  ask max-one-of digit [ xcor ]
    [ set here-x xcor
      set here-y ycor
    ]
  ask digit
    [ set heading -90 ]
  ask min-one-of digit [ xcor ]
    [ set heading 180
      repeat offset
        [  fd 1
           wait med-slow
        ]
      set heading 90
    ]
  set flag false
  set n 0
  ask digit
    [  repeat offset
          [  fd 1
             wait med-slow
          ]
    ]
  ask digit with [ ycor != here-y ]
    [
      while [ xcor < here-x ]
        [ fd 1
          wait med-slow
        ]
      set heading 0
      repeat offset
        [  fd 1
           wait med-slow
        ]
    ]
  set step (step + 1)
end

to step4
  locals [ here-y here-x offset]
  explain 1 "Pad to an even number of nibbles."
  set offset 15
  ifelse (count digit) mod 2 = 1
    [  ; odd
       explain 2 (count digit) + " nibbles, so must pad."
       ask min-one-of digit [ xcor ]
          [ set here-x xcor
            set here-y ycor
          ]
       cct-digit 1 [
              set label "1111"
              setxy (here-x - 30) here-y
              set heading 90
              set color black
              set label-color yellow
            ]
       ask digit with [ label = "1111" ]
         [  while [ xcor < (here-x - offset) ]
               [  fd 1
                  wait slow-motion
               ]
         ]
    ]
    [  ; even
       explain 2 (count digit) + " nibbles, so no padding needed."
       wait slow-motion * 3
    ]
  set step (step + 1)

end

to step5
  locals [ current digit-list med-slow ]
  explain 1 "Pack two nibbles into each byte."
  explain 2 ""
  set med-slow slow-motion / 5
  ask digit
    [ set state "ready" ]
  set digit-list digit with [ state = "ready"]
  
  while [ count digit-list > 1 ]
  [
    set current min-one-of digit-list [ xcor ]
    ask current
      [  set heading 90
         while [ not any? other-digit-here ]
            [  fd 1
               wait med-slow
            ]
         set label (label + " " + label-of random-one-of other-digit-here)
         set label-color cyan
         ask other-digit-here
           [ die ]
         set state "done"
      ]  
    set digit-list digit with [ state = "ready"]
  ]

  set step (step + 1)
end

to step6
  explain 1 "Decimal number: " + add-commas save-from-number
  explain 2 "Packed BCD: " + add-spaces get-number
  set step 9
  set doneyet? true
end

to-report get-number
  locals [ current digit-list result ]
  set digit-list digit
  set result ""
  while [count digit-list > 0]
  [ set current min-one-of digit-list [ xcor ]
    ask current
      [ set result result + label 
        set breed from-digit
      ]
    set digit-list digit
  ]
  report result
end

;  do a single step (whichever comes next)
to one-step
  locals [  which-step]
  set which-step "step" + step
  if ( step < 8)
    [ run which-step ]
end


;  return randomly "0" or "1"
to-report random-bit
  locals [ ch ]
  ifelse random 100 < 50
    [ set ch "0" ]
    [ set ch "1" ]
  report ch
end

;  show remaining steps
to go
  locals [  which-step]
  set which-step "step" + step
  ifelse not doneyet? 
    [ run which-step
      set which-step "step" + step
      wait slow-motion
    ]
    [ stop
    ]
end

;  add a comma every three bits, so the user won't make copy errors
to-report add-commas [ number ]
  locals [ save k sign ]
  set sign ""
  if member? (first number) [ "-" "+" ]
    [ set sign first number
      set number but-first number
    ]
  set save ""
  set k 0
  while [ (length number) > 0 ]
    [
      set save (word last number save )
      set number butlast number
      set k (k + 1)
      if (k = 3) and (length number > 0)
        [ set save (word "," save )
          set k 0
        ]
    ]
  set number (word sign save )
  report number
end

;  add a space every four bits, so the user won't make copy errors
to-report add-spaces [ number ]
  locals [ save k ]
  set save ""
  set k 0
  set number remove " " number
  while [ (length number) > 0 ]
    [
      set save (word last number save )
      set number butlast number
      set k (k + 1)
      if (k = 4) and (length number > 0)
        [ set save (word " " save )
          set k 0
        ]
    ]
  set number save  
  report number
end

; *** NetLogo Model Copyright Notice ***
;
; Copyright 2004 by Teresa W. Carrigan.  All rights reserved.
;
; Permission to use, modify or redistribute this model is hereby granted,
; provided that both of the following requirements are followed:
; a) this copyright notice is included.
; b) this model will not be redistributed for profit without permission
;    from Teresa W. Carrigan.
; Contact Teresa W. Carrigan for appropriate licenses for redistribution 
; for profit.
;
; To refer to this model in academic publications, please use:
; Carrigan, T. (2004).  Packed Binary Coded Decimal Simulation model.
; Blackburn College, Carlinville IL.
;
; In other publications, please use:
; Copyright 2004 by Teresa W. Carrigan.  All rights reserved.  
;
; *** End of NetLogo Model Copyright Notice ***
@#$#@#$#@
GRAPHICS-WINDOW
3
10
665
341
81
37
4.0
1
18
1
1
1

CC-WINDOW
18
388
399
499
Command Center

BUTTON
3
344
86
377
NIL
setup
NIL
1
T
OBSERVER
T

SLIDER
338
345
511
378
slow-motion
slow-motion
0
1
0.3
0.1
1
seconds

BUTTON
87
344
169
377
step
one-step
NIL
1
T
OBSERVER
T

BUTTON
169
344
238
377
go
go
T
1
T
OBSERVER
T

BUTTON
239
345
337
378
show-again
restart
NIL
1
T
OBSERVER
T

@#$#@#$#@
WHAT IS IT?
-----------
This model demonstrates Packed Binary Coded Decimal character coding.  Each decimal digit is converted separately to binary, and stored in one nibble.


HOW IT WORKS
------------
A random decimal number is generated, with 2 to 9 digits, and a random sign of either "+" or "-".  The sign is moved to the far right, and then each character is converted to a binary nibble.  If the number of nibbles is odd, we add one extra nibble of padding (1111) at the far left.  Two nibbles are stored in each byte.  

HOW TO USE IT
-------------
The setup button generates a decimal number, and initializes variables.

The slow-motion slider is an easy way to adjust the speed of the display.  Set it to zero if you want to show the final result as quickly as possible.  0.3 is a good setting for most purposes.

The step button demonstrates the next step of the method.  It then stops so you can take notes.  This is useful when you are first learning the method.

The go button demonstrates the remaining steps, at a speed determined by the slow-motion slider.  This is useful when you do not need to take notes between each step, or do not wish to press the step button sixteen times to get an answer.  If you want to pause the demonstration, simply click the go button a second time and it will stop after it finishes the current step.  You may then click go a third time to resume.

The show-again button restarts the demonstration using the same decimal number, so that you can see the same problem several times if you wish.

THINGS TO NOTICE
----------------
A packed BCD representation takes more bits than using normal binary representations, but has more flexibility.  For example, even if the memory locations and registers are restricted to 64 bit numbers (so a two's complement integer would be limited to 32 bits) a packed BCD number could have an arbitrary number of bytes with two digits per byte.

THINGS TO TRY
-------------
Set slow-motion to 0.3, then click go.

Click setup.  Attempt one step at a time on paper, and then click the step button to check that you did that step correctly.

EXTENDING THE MODEL
-------------------
Allow the user to input a starting decimal number.

Modify so that the packed BCD bit pattern is generated first, and then conversion to decimal is demonstrated.

Modify the model to demonstrate zoned-decimal coding.

NETLOGO FEATURES
----------------
Instead of converting each decimal digit to binary every time we process a digit, the different characters and bit patterns are stored in lists once.  When we process a character from the decimal number, the lookup procedure simply uses "set n position what from-list report item n to-list"

RELATED MODELS
--------------
Binary Counter, Successive Division


CREDITS AND REFERENCES
----------------------
This model was written by Teresa W. Carrigan, 2004.  

Permission to use, modify or redistribute this model is hereby granted,
provided that both of the following requirements are followed:
	a) this copyright notice is included.
	b) this model will not be redistributed for profit without permission
	   from Teresa W. Carrigan.
Contact Teresa W. Carrigan for appropriate licenses for redistribution 
for profit.

To refer to this model in academic publications, please use: 
Carrigan, T. (2004). Packed Binary Coded Decimal Simulation model. 
Blackburn College, Carlinville, IL.

In other publications, please use: 
Copyright 2004 by Teresa W. Carrigan.  All rights reserved.  

FOR MORE INFORMATION
--------------------
For more information on binary coded decimal, see:
Null, L. and Lobur, J. "Essentials of Computer Organization and Architecture", First Edition, Jones and Bartlett, pages 62-63.


@#$#@#$#@
default
true
0
Polygon -7566196 true true 150 5 40 250 150 205 260 250

box
true
0
Polygon -7566196 true true 45 255 255 255 255 45 45 45

circle
false
0
Circle -7566196 true true 35 35 230

@#$#@#$#@
NetLogo 2.0.1
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
