class TraceSegment:
- """ Models a straight line segment of a complete Trace """
- # N NE E SE S SW W NW
- angles = ( 0 , 45 , 90, 135, 180, 225, 270, 315)
+ """ Models a straight line segment of a complete Trace and any associated Via (through-hole)
+ A segment may only have at most 1 Via
- # references to an attached Via and its position
- via = None
- via_position = None
+ The direction is limited to 8 points on the compass
+
+ The length is an arbitrary multiplier. The game itself will decide how many pixels represent
+ the minimum length of a segment. Suggestion is that the value be the minimum width of cells in
+ the game-map matrix if a tile-based model of the playing area is in use.
+ """
def __init__(self, length=1, direction=library.directions.E, via=None, via_position=library.positions.NONE):
""" default segment runs for one game tile length left-to-right
- length: number of game 'tiles' this segment covers
- direction: enum directions
- via: Via
- via_position: enum positions
+ length: number of game 'tiles' this segment covers (default = 1)
+ direction: enum directions (default = East)
+ via: Via (default = None)
+ via_position: enum positions (default = NONE)
"""
+ # N NE E SE S SW W NW
+ self.angles = ( 0 , 45 , 90, 135, 180, 225, 270, 315)
+
+ # references to an attached Via and its position
+ self.via = None
+ self.via_position = None
+
# ensure all values are legal before doing any assignment
if not direction in library.directions.reverse_mapping:
# 'direction' is an index enum, so ensure it exists in the enum before using it to select the angle
class Trace:
""" Models a single circuit trace made up of multiple segments """
- segments = list() # ordered list of one or more TraceSegments
- colours = dict()
- # colours['metal'] = (192, 192, 192) # colours of the trace
- # colours['shadow'] = (64, 64, 64)
- # colours['reflection'] = (255, 255, 255)
- def check_range(self, colour):
- """ Ensure a colour value is legal """
- if not (type(colour) == tuple or type(colour) == int):
- raise TypeError('colour expeted to be tuple or int')
- elif not len(colour) == 3:
- raise ValueError('colour tuples require exactly 3 items (RGB)')
+ def __init__(self, metal=(192, 192, 192), shadow=(64, 64, 64), reflection=(255, 255, 255), segments=None):
+ self.segments = list() # ordered list of one or more TraceSegments
+ self.colours = dict()
- if type(colour) == int:
- return colour >= 0 and colour <= 255
- else:
- return self.check_range(colour[0]) and self.check_range(colour[1]) and self.check_range(colour[2])
+ # colours['metal'] = (192, 192, 192) # colours of the trace
+ # colours['shadow'] = (64, 64, 64)
+ # colours['reflection'] = (255, 255, 255)
- def __init__(self, metal=(192, 192, 192), shadow=(64, 64, 64), reflection=(255, 255, 255), segments=None):
# set the colours of the trace to give a 3D raised appearance
if metal and check_range(metal): self.colours['metal'] = metal
if shadow and check_range(shadow): self.colours['shadow'] = shadow
via = None
via_position = library.positions.NONE
+ def check_range(self, colour):
+ """ Ensure a colour value is legal """
+ if not (type(colour) == tuple or type(colour) == int):
+ raise TypeError('colour expeted to be tuple or int')
+ elif not len(colour) == 3:
+ raise ValueError('colour tuples require exactly 3 items (RGB)')
+
+ if type(colour) == int:
+ return colour >= 0 and colour <= 255
+ else:
+ return self.check_range(colour[0]) and self.check_range(colour[1]) and self.check_range(colour[2])
+
def draw(self, surface):
""" Draw the Trace onto pygame.Surface """
return
class Via:
""" Models a through-hole otherwise known as a Via """
- trace = None # the Trace this via is attached to
- linked = None # the Via this via links to
+
+ def __init__(self):
+ self.trace = None # the Trace this via is attached to
+ self.linked = None # the Via this via links to
class Bus:
""" Group of traces all going in the same direction """
- width = 8 # default is an 8-bit bus
- group = None
def __init__(self, buswidth=8):
""" Create a new bus consisting of 'buswidth' traces """
+ self.BUSWIDTH_MAX = 32
+ if not (buswidth >= 1 and buswidth <= self.BUSWIDTH_MAX):
+ raise ValueError('bus width out of range')
+
+ self.width = 8 # default is an 8-bit bus
+ self.group = None
class IntegratedCircuit:
""" semiconductor component """
- pins = list() # index = pin number, value = signal name
+
+ def __init__(self):
+ self.pins = list() # index = pin number, value = signal name
class DualInLine(IntegratedCircuit):
""" Dual In-Line Integrated Circuit """
- sides = 2
- qty = 0
def __init__(self, pin_qty):
+ self.sides = 2
+ self.qty = 0
+
if not (pin_qty > 0 and pin_qty % 2 == 0):
raise ValueError('DIL ICs have even number of pins')
class Gate:
""" Models a single logic gate """
- types = None
- inputs = list()
- output = False
- gate_type = None
def __init__(self, gate_type, inputs=None):
+ self.inputs = list()
+ self.output = False
+ self.gate_type = None
+
if not gate_type in library.gates:
raise IndexError()
self.inputs = inputs
self.input_max = len(self.inputs)
- self.update()
+ self.update_state()
- def update(self):
+ def update_state(self):
""" Needs to be over-ridden in derived classes """
return
raise TypeError('Boolean expected')
self.inputs[input] = value
- self.update()
+ self.update_state()
def get_output(self):
return self.output
# Derive each of the common logic gate types
class GateAND(Gate):
- def __init__(self, inputs=None):
- Gate.__init__(library.gates.AND, self.min_inputs(inputs, 2))
- def update(self):
+ def update_state(self):
self.output = self.inputs[0]
for i in range(1, self.input_max):
self.output &= self.inputs[i] # AND
def __init__(self, inputs=None):
Gate.__init__(library.gates.OR, self.min_inputs(inputs, 2))
- def update(self):
+ def update_state(self):
self.output = self.inputs[0]
for i in range (1, self.input_max):
self.output |= self.inputs[i] # OR
def __init__(self, inputs=None):
Gate.__init__(library.gates.XOR, self.min_inputs(inputs, 2))
- def update(self):
+ def update_state(self):
self.output = self.inputs[0]
for i in range (1, self.input_max):
self.output ^= self.inputs[i] # XOR
raise ValueError('NOT must have only 1 input')
Gate.__init__(library.gates.NOT, inputs)
- def update(self):
+ def update_state(self):
self.output = ~self.inputs[0] # invert
def __init__(self, inputs=None):
Gate.__init__(library.gates.NAND, self.min_inputs(inputs, 2))
- def update(self):
+ def update_state(self):
self.output = self.inputs[0]
for i in range(1, self.input_max):
self.output &= self.inputs[i] # AND
def __init__(self, inputs=None):
Gate.__init__(library.gates.NOR, self.min_inputs(inputs, 2))
- def update(self):
+ def update_state(self):
self.output = self.inputs[0]
for i in range (1, self.input_max):
self.output |= self.inputs[i] # OR
class ICLogic:
""" Models an IC that contains one or more digital logic gates """
- gates = list() # list of gates
def __init__(self, gates=()):
+ self.gates = list()
+
if not type(gates) is list:
raise TypeError('expected list')
elif not type(gates[0]) is Gate:
raise TypeError('expected Gate')
- self.gates = gates
+ self.gates.append(gates)
def add(self, gate):
if not type(gate) is Gate:
class ICLogicDIL(ICLogic, DualInLine):
""" Model of a Logic IC ina DIL package """
+ def __new__(cls, *args):
+ print("ICLoigcDIL.__new__()")
+
def __init__(self, gates=(), pins_qty=14):
+ print('ICLogicDL.__slots__ =',self. __slots__)
ICLogic.__init(gates)
DualInLine.__init__(pins_qty)
class TSSOP(IntegratedCircuit):
""" Thin Shrink Small Outline Package """
- sides = 2
- pins = list()
+ # emulate C++/Java classes
+ __slots__ = ['sides', 'pins']
def __init__(self, pins):
+ self.sides = 2
+ self.pins = list()
return
class PCB:
""" Models a digital electronics logic circuit printed on a circuit board """
- layout = None
def __init__(self):
""" """
+ self.layout = None
return
def trace_add(self, trace_list):
""" Adds a component to the circuit """
return
+