Class: Badline::CIA
- Inherits:
-
Object
- Object
- Badline::CIA
- Extended by:
- Forwardable
- Includes:
- Addressable
- Defined in:
- lib/badline/cia.rb,
lib/badline/cia/timer.rb
Overview
CIA (Complex Interface Adapter) chip
Defined Under Namespace
Classes: Timer
Instance Attribute Summary collapse
-
#control_a ⇒ Object
readonly
Returns the value of attribute control_a.
-
#control_b ⇒ Object
readonly
Returns the value of attribute control_b.
-
#interrupt_control ⇒ Object
readonly
Returns the value of attribute interrupt_control.
-
#interrupt_status ⇒ Object
readonly
Returns the value of attribute interrupt_status.
-
#peripheral ⇒ Object
readonly
Returns the value of attribute peripheral.
-
#start ⇒ Object
readonly
Returns the value of attribute start.
Attributes included from Addressable
Instance Method Summary collapse
- #cycle! ⇒ Object
-
#initialize(start: 0, peripheral: nil) ⇒ CIA
constructor
A new instance of CIA.
- #interrupt!(delay = 1) ⇒ Object
- #interrupted? ⇒ Boolean
- #peek(addr) ⇒ Object
- #poke(addr, value) ⇒ Object
-
#port_a_lines ⇒ Object
Port A as driven by the data/direction registers alone, without peripheral pulldown.
- #read_port_a ⇒ Object
- #read_port_b ⇒ Object
Methods included from Addressable
#[], #[]=, #addressable_at, #in_range?, #peek16, #poke16, #range
Methods included from IntegerHelper
#bcd, #bcd_to_i, #format16, #format8, #high_byte, #low_byte, #signed_int8, #uint16
Constructor Details
#initialize(start: 0, peripheral: nil) ⇒ CIA
Returns a new instance of CIA.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/badline/cia.rb', line 23 def initialize(start: 0, peripheral: nil) addressable_at(start, length: 2**8) @peripheral = peripheral @data_port_a = 0xff @data_port_b = 0xff @data_dir_a = 0xff @data_dir_b = 0x0 @irq_pending = 0 @serial_data = 0x0 @tod = TimeOfDay.new @interrupt_control = Status.new([:timer_a, :timer_b, :alarm, :serial, :flag, 0, 0, 0]) @interrupt_status = Status.new([:timer_a, :timer_b, :alarm, :serial, :flag, 0, 0, :interrupt]) @control_a = Status.new(%i[start output out_mode run_mode load in_mode serial_mode clock_frequency]) @control_b = Status.new(%i[start output out_mode run_mode load in_cnt in_timer_a alarm]) @ta = Timer.new(@control_a) @tb = Timer.new(@control_b) end |
Instance Attribute Details
#control_a ⇒ Object (readonly)
Returns the value of attribute control_a.
12 13 14 |
# File 'lib/badline/cia.rb', line 12 def control_a @control_a end |
#control_b ⇒ Object (readonly)
Returns the value of attribute control_b.
12 13 14 |
# File 'lib/badline/cia.rb', line 12 def control_b @control_b end |
#interrupt_control ⇒ Object (readonly)
Returns the value of attribute interrupt_control.
12 13 14 |
# File 'lib/badline/cia.rb', line 12 def interrupt_control @interrupt_control end |
#interrupt_status ⇒ Object (readonly)
Returns the value of attribute interrupt_status.
12 13 14 |
# File 'lib/badline/cia.rb', line 12 def interrupt_status @interrupt_status end |
#peripheral ⇒ Object (readonly)
Returns the value of attribute peripheral.
12 13 14 |
# File 'lib/badline/cia.rb', line 12 def peripheral @peripheral end |
#start ⇒ Object (readonly)
Returns the value of attribute start.
12 13 14 |
# File 'lib/badline/cia.rb', line 12 def start @start end |
Instance Method Details
#cycle! ⇒ Object
54 55 56 57 58 59 60 61 |
# File 'lib/badline/cia.rb', line 54 def cycle! if @irq_pending.positive? @irq_pending -= 1 interrupt_status.interrupt = true if @irq_pending.zero? end update_timers @tod.cycle! { trigger_alarm } end |
#interrupt!(delay = 1) ⇒ Object
46 47 48 |
# File 'lib/badline/cia.rb', line 46 def interrupt!(delay = 1) @irq_pending = @irq_pending.positive? ? [@irq_pending, delay].min : delay end |
#interrupted? ⇒ Boolean
50 51 52 |
# File 'lib/badline/cia.rb', line 50 def interrupted? interrupt_status.value.anybits?(0x80) end |
#peek(addr) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/badline/cia.rb', line 80 def peek(addr) case index(addr) & 0x0f when 0x00 then read_port_a when 0x01 then read_port_b when 0x02 then @data_dir_a when 0x03 then @data_dir_b when 0x04 then low_byte(@ta.counter) when 0x05 then high_byte(@ta.counter) when 0x06 then low_byte(@tb.counter) when 0x07 then high_byte(@tb.counter) when 0x08 then @tod.tenths when 0x09 then @tod.seconds when 0x0a then @tod.minutes when 0x0b then @tod.hours when 0x0c then @serial_data when 0x0d value = interrupt_status.value interrupt_status.value = 0x0 # Burn after reading @irq_pending = 0 value when 0x0e then control_a.value when 0x0f then control_b.value end end |
#poke(addr, value) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/badline/cia.rb', line 105 def poke(addr, value) case index(addr) & 0x0f when 0x00 then @data_port_a = value when 0x01 then @data_port_b = value when 0x02 then @data_dir_a = value when 0x03 then @data_dir_b = value when 0x04 then @ta.write_latch_low(value) when 0x05 then @ta.write_latch_high(value) when 0x06 then @tb.write_latch_low(value) when 0x07 then @tb.write_latch_high(value) when 0x08 then @tod.write(:tenths, value, alarm: control_b.alarm?) when 0x09 then @tod.write(:seconds, value, alarm: control_b.alarm?) when 0x0a then @tod.write(:minutes, value, alarm: control_b.alarm?) when 0x0b then @tod.write_hours(value, alarm: control_b.alarm?) when 0x0c # TODO: Serial when 0x0d then write_interrupt_control(value) when 0x0e then @ta.write_control(value) when 0x0f then @tb.write_control(value) end end |
#port_a_lines ⇒ Object
Port A as driven by the data/direction registers alone, without peripheral pulldown. Cheap path for the VIC bank lookup.
70 71 72 |
# File 'lib/badline/cia.rb', line 70 def port_a_lines driven_lines(@data_port_a, @data_dir_a) end |
#read_port_a ⇒ Object
63 64 65 66 |
# File 'lib/badline/cia.rb', line 63 def read_port_a pulldown = peripheral ? peripheral.read_a(@data_port_a, @data_port_b) : 0xff driven_lines(@data_port_a, @data_dir_a) & pulldown end |
#read_port_b ⇒ Object
74 75 76 77 78 |
# File 'lib/badline/cia.rb', line 74 def read_port_b pulldown = peripheral ? peripheral.read_b(@data_port_a, @data_port_b) : 0xff value = driven_lines(@data_port_b, @data_dir_b) & pulldown apply_timer_output(value) end |