|
| 1 | +// The idea is that we have a free running timer that is incremented by the CPU clock. |
| 2 | +// When a decay happens the joystick button is pressed by a transistor connected between fire button and ground. |
| 3 | +// As the button is pressed the LSB of the timer B is read and shifted into a byte when 8 bits are filled we have |
| 4 | +// a truly random byte generated |
| 5 | +// we actually generate 255 bytes in total, so we can do some analysis on the distribution of the bytes |
| 6 | +// those random bytes start at $2000 (8192) |
| 7 | +// Since we use a free running timer that we read when a decay happens, we avoid system entropy. |
| 8 | +.const CONT_TIMER_B = $DC0F |
| 9 | +.const LSB_TIMER_B = $DC06 |
| 10 | +.const CURRENT_SCANLINE = $D012 |
| 11 | +.const JOYSTICK_2 = $DC00 |
| 12 | +.const SCREEN_MEM = $0400 |
| 13 | + |
| 14 | +BasicUpstart2(main) |
| 15 | + |
| 16 | +*=$1000 |
| 17 | +main: |
| 18 | + jsr setup |
| 19 | + jsr start_timer_b |
| 20 | + |
| 21 | +loop: |
| 22 | + // the detector has a 10ms pulse so we wait max 40ms for the next decay, so we don't flood the whole byte with same bit |
| 23 | + jsr wait_for_raster_line // give a 20 ms wait |
| 24 | + jsr wait_for_raster_line // give a 20 ms wait |
| 25 | + |
| 26 | + jsr wait_for_decay_pulse // wait till the isotope decays |
| 27 | + |
| 28 | + jsr mask_lowest_bit //mask the lowest bit of timer B and if 1 shift without add if 0 shift with add of 1 |
| 29 | + bne !shift_add_1+ // if 0 shift left and add one |
| 30 | + |
| 31 | + jsr shift_add_nothing // if 1 shift left and don't add one |
| 32 | + beq !back_to_basic+ // if sub routine set Z flag then exit to basic |
| 33 | + jmp loop // read the next pulse |
| 34 | + |
| 35 | +!shift_add_1: |
| 36 | + jsr shift_add_1 // shift left and add 1 to the intermediate result in random_result byte that offset x points to |
| 37 | + beq !back_to_basic+ // if subroutine set Z flag then exit to basic |
| 38 | + jmp loop // read next bit |
| 39 | + |
| 40 | +//Exit to basic gracefully |
| 41 | +!back_to_basic: |
| 42 | + sei |
| 43 | + lda #$37 |
| 44 | + sta $01 |
| 45 | + cli |
| 46 | + jsr $ff8a |
| 47 | + jsr $ff81 |
| 48 | + jsr $ff84 |
| 49 | + rts |
| 50 | + |
| 51 | + |
| 52 | +// |
| 53 | +//SUBROUTINES |
| 54 | +// |
| 55 | + |
| 56 | +//sets up the counters |
| 57 | +setup: |
| 58 | + lda CONT_TIMER_B // load the configuration of TIMER B |
| 59 | + and #%1000101 // configure to count clock cycles |
| 60 | + ora #%0000000 // start the timer |
| 61 | + sta CONT_TIMER_B // store the timer config and start |
| 62 | + ldx #$00 // offset ponter into random_bytes array |
| 63 | + ldy #$00 // ofset pointer to bit in the random_byte pointed to by random_bytes+x |
| 64 | + rts |
| 65 | + |
| 66 | +// start the timer B again |
| 67 | +start_timer_b: |
| 68 | + ora #%00000001 //start timer B again |
| 69 | + sta CONT_TIMER_B //set timer B register |
| 70 | + rts |
| 71 | + |
| 72 | +// this waits for raster line ff to give a bit of a delay |
| 73 | +wait_for_raster_line: |
| 74 | + !wait: |
| 75 | + lda CURRENT_SCANLINE // read current rasterline |
| 76 | + cmp $ff // if current rasterline is not ff than wait |
| 77 | + bne !wait- |
| 78 | + rts |
| 79 | + |
| 80 | +// wait for the joystick button (which is triggered by the geiger counter when a isotope decays) |
| 81 | +wait_for_decay_pulse: |
| 82 | + !await_pulse: |
| 83 | + //poll joystick button, a button press is a tick from the geiger counter |
| 84 | + lda JOYSTICK_2 // read joystick 2 |
| 85 | + and #$10 // check button pressed |
| 86 | + bne !await_pulse- // no new decay measured than wait |
| 87 | + rts |
| 88 | + |
| 89 | +// mask the lowerst bit of timer b LSB value |
| 90 | +mask_lowest_bit: |
| 91 | + lda LSB_TIMER_B // read lsb of timer B |
| 92 | + and #$1 // mask lowest bit to see if the timer B count is odd or eveb |
| 93 | + rts |
| 94 | + |
| 95 | +// shift the value in random_bytes+x left one position |
| 96 | +shift_add_nothing: |
| 97 | + lda random_bytes,X // load the current random byte (X is the offset into the 255 random bytes) |
| 98 | + asl // if even just shift result left without adding one to the result |
| 99 | + jsr prep_for_next_bit // set everything up for the next bit (or next byte) |
| 100 | + rts |
| 101 | + |
| 102 | +// shidt the value in random_bytes+x left one position and set the lowest bit to 1 |
| 103 | +shift_add_1: |
| 104 | + lda random_bytes,X // load the current random byte (X is the offset into the 255 random bytes) |
| 105 | + asl // shift the temporary random result left |
| 106 | + ora #$01 // add one to the result |
| 107 | + jsr prep_for_next_bit // set everything up for the next bit (or next byte) |
| 108 | + rts |
| 109 | + |
| 110 | +//prepare the offset to y for the next bit, if y is 8 then set to 0 and increment x pointer |
| 111 | +prep_for_next_bit: |
| 112 | + sta random_bytes,X //store the temporary random byte back into the array |
| 113 | + iny //increment the bit counter |
| 114 | + cpy #$08 //if bit counter is 8 then reset bit counter and increment array counter to fill next byte |
| 115 | + beq !reset_y+ //if y==8 then reset |
| 116 | + rts |
| 117 | + !reset_y: |
| 118 | + jsr reset_y // reset y to 0 |
| 119 | + rts |
| 120 | + |
| 121 | +reset_y: |
| 122 | + jsr print_bit_pattern // print the current byte to the screen |
| 123 | + ldy #$00 // reset the bit counter to 0 |
| 124 | + inx // since y was 8, it means we should also increment x to point to the next random byte |
| 125 | + rts |
| 126 | + |
| 127 | +print_bit_pattern: |
| 128 | + // store a and y to the stack |
| 129 | + pha |
| 130 | + tya |
| 131 | + pha |
| 132 | + |
| 133 | + ldy #%000000001 // load bit pattern to #%000000001 |
| 134 | + sty bit_pattern // store bit pattern |
| 135 | + ldy #8 // 8 bits to print |
| 136 | + |
| 137 | + !loop: |
| 138 | + lda random_bytes, X // load the random byte from the array |
| 139 | + and bit_pattern // mask the random byte with the bit pattern |
| 140 | + beq !draw_zero+ |
| 141 | + |
| 142 | +!draw_one: |
| 143 | + lda #49 |
| 144 | + jmp !draw_bit+ |
| 145 | + |
| 146 | +!draw_zero: |
| 147 | + adc #48 |
| 148 | + |
| 149 | + !draw_bit: |
| 150 | + rol bit_pattern |
| 151 | + sta SCREEN_MEM,y // draw the bit to the screen starting from 400 with offset y |
| 152 | + dey // decrement the bit counter |
| 153 | + bne !loop- // if bit counter is not 0 then loop again |
| 154 | + |
| 155 | + // restore a and y from the stack |
| 156 | + pla |
| 157 | + tay |
| 158 | + pla |
| 159 | + rts |
| 160 | + |
| 161 | +*=$2000 "random bytes" |
| 162 | +// array that holds the 255 random bytes that were generated |
| 163 | +random_bytes: .fill 255,00 |
| 164 | +bit_pattern: .byte 0 |
0 commit comments