nixfilter-logicsignal
Version:
Filters for handling (compressing/uncompressing etc.) logic signals
97 lines (82 loc) • 3.68 kB
text/coffeescript
'use strict'
# Returns true if the passed argument <value> is neither null nor undefined
is_valid_value = (value) ->
((value isnt undefined) and (value isnt null))
# Returns the first value in <values...> that is neither null nor undefined
first_valid_value = (values...) ->
for value in values
if is_valid_value(value)
return value
return
# Assuming that array <array> can be constructed by repeating another array n times, returns the largest n
get_number_of_repetitions_in_array = (array) ->
for number_of_repetitions in [array.length..2] by -1
if ((array.length % number_of_repetitions) is 0)
repeated_array_length = (array.length // number_of_repetitions)
for index in [repeated_array_length...array.length] by 1
if (array[index] isnt array[index % repeated_array_length])
break
if (index is array.length)
return number_of_repetitions
1
# Returns the greatest common divisor (GCD) of <first_number> and <second_number>
greatest_common_divisor = (first_number, second_number) ->
return (if first_number then greatest_common_divisor(second_number % first_number, first_number) else second_number)
# Returns the greatest_common_divisor (GCD) of all numbers in array <numbers_array>
greatest_common_divisor_in_array = (numbers_array) ->
numbers_array.reduce(greatest_common_divisor)
# Returns true if <value> is an array
is_array = (value) ->
Array.isArray(value)
# Returns a function with <value> argument that returns true if <value> is of type <type_string>
is_of_type = (type_string) ->
(value) ->
(typeof(value) is type_string)
# Returns true if <value> is of type "string"
is_object_type = is_of_type('object')
# Returns true if <value> is of type "string"
is_string_type = is_of_type('string')
# The regular expression pattern of a valid logic signal, as a string
logic_signal_pattern = '^\\s*\\[?(\\s*[+-]?\\d+?(?:,\\s*[+-]?\\d+)*)\\]?(?:\\s*@\\s*(\\d+))?(?:\\s*\\*\\s*(\\d+))?\\s*$'
# The regular expression pattern of a valid logic signal, as a RegExp
logic_signal_regexp = (new RegExp(logic_signal_pattern))
# Repeat array <array> <number_of_repetitions> times
repeat_array = (array, number_of_repetitions) ->
(array[index % array.length] for index in [0...(array.length * number_of_repetitions)] by 1)
# This class represents a logic/binary signal
Logic_Signal = class
constructor: (data, cycle_time, repetitions) ->
if is_array(data)
= data
= cycle_time
= repetitions
else if is_object_type(data)
= data.cycles
= data.cycle_time
= data.repetitions
else if is_string_type(data)
data = logic_signal_regexp.exec(data)
= (parseInt(cycle_string) for cycle_string in data[1].split(','))
= data[2]
= data[3]
else
throw new Error('Logic signal constructor called with invalid arguments')
= first_valid_value(, 1)
= first_valid_value(, 1)
get_unrepeated_timings: ->
.map((cycle) => (cycle * ))
get_timings: ->
repeat_array(, )
compress: ->
timings =
repetitions = get_number_of_repetitions_in_array(timings)
unrepeated_timings = timings.slice(0, (timings.length // repetitions))
cycle_time = greatest_common_divisor_in_array(unrepeated_timings)
cycles = ((timing // cycle_time) for timing in unrepeated_timings)
new Logic_Signal(cycles, cycle_time, repetitions)
to_string: ->
"#{@cycles.join(',')}@#{@cycle_time}*#{@repetitions}"
to_timings_string: ->
.join(',')
# What this module exports
module.exports = Logic_Signal