KLL Compiler
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

id.py 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. #!/usr/bin/env python3
  2. '''
  3. KLL Id Containers
  4. '''
  5. # Copyright (C) 2016 by Jacob Alexander
  6. #
  7. # This file is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This file is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this file. If not, see <http://www.gnu.org/licenses/>.
  19. ### Imports ###
  20. from common.hid_dict import hid_lookup_dictionary
  21. from common.channel import ChannelList
  22. from common.modifier import AnimationModifierList, PixelModifierList
  23. from common.position import Position
  24. from common.schedule import Schedule
  25. ### Decorators ###
  26. ## Print Decorator Variables
  27. ERROR = '\033[5;1;31mERROR\033[0m:'
  28. WARNING = '\033[5;1;33mWARNING\033[0m:'
  29. ### Classes ###
  30. class Id:
  31. '''
  32. Base container class for various KLL types
  33. '''
  34. def __init__( self ):
  35. self.type = None
  36. self.uid = None
  37. class HIDId( Id, Schedule ):
  38. '''
  39. HID/USB identifier container class
  40. '''
  41. secondary_types = {
  42. 'USBCode' : 'USB',
  43. 'SysCode' : 'SYS',
  44. 'ConsCode' : 'CONS',
  45. 'IndCode' : 'IND',
  46. }
  47. def __init__( self, type, uid ):
  48. '''
  49. @param type: String type of the Id
  50. @param uid: Unique integer identifier for the Id
  51. '''
  52. Id.__init__( self )
  53. Schedule.__init__( self )
  54. self.type = type
  55. self.uid = uid
  56. # Set secondary type
  57. self.second_type = self.secondary_types[ self.type ]
  58. # TODO Validate uid to make sure it's in the lookup dictionary
  59. # TODO Validate HID specifier
  60. #print ( "{0} Unknown HID Specifier '{1}'".format( ERROR, type ) )
  61. #raise
  62. def __repr__( self ):
  63. '''
  64. Use string name instead of integer, easier to debug
  65. '''
  66. uid = hid_lookup_dictionary[ ( self.second_type, self.uid ) ]
  67. schedule = self.strSchedule()
  68. if len( schedule ) > 0:
  69. schedule = "({0})".format( schedule )
  70. output = 'HID({0})"{1}"{2}'.format( self.type, uid, schedule )
  71. return output
  72. class ScanCodeId( Id, Schedule, Position ):
  73. '''
  74. Scan Code identifier container class
  75. '''
  76. def __init__( self, uid ):
  77. Id.__init__( self )
  78. Schedule.__init__( self )
  79. Position.__init__( self )
  80. self.type = 'ScanCode'
  81. self.uid = uid
  82. # By default, interconnect_id of 0
  83. # Will be set during the merge process if it needs to change
  84. self.interconnect_id = 0
  85. def unique_key( self ):
  86. '''
  87. Returns the key string used for datastructure sorting
  88. '''
  89. # Positions are a special case
  90. if self.positionSet():
  91. return "P{0}".format( self.uid )
  92. def __repr__( self ):
  93. # Positions are a special case
  94. if self.positionSet():
  95. return "{0} <= {1}".format( self.unique_key(), self.strPosition() )
  96. schedule = self.strSchedule()
  97. if len( schedule ) > 0:
  98. return "S{0}({1})".format( self.uid, schedule )
  99. else:
  100. return "S{0}".format( self.uid )
  101. class AnimationId( Id, AnimationModifierList ):
  102. '''
  103. Animation identifier container class
  104. '''
  105. name = None
  106. def __init__( self, name ):
  107. Id.__init__( self )
  108. AnimationModifierList.__init__( self )
  109. self.name = name
  110. self.type = 'Animation'
  111. def __repr__( self ):
  112. if len( self.modifiers ) > 0:
  113. return "A[{0}]({1})".format( self.name, self.strModifiers() )
  114. return "A[{0}]".format( self.name )
  115. class AnimationFrameId( Id, AnimationModifierList ):
  116. '''
  117. Animation Frame identifier container class
  118. '''
  119. def __init__( self, name, index ):
  120. Id.__init__( self )
  121. AnimationModifierList.__init__( self )
  122. self.name = name
  123. self.index = index
  124. self.type = 'AnimationFrame'
  125. def __repr__( self ):
  126. return "AF[{0}, {1}]".format( self.name, self.index )
  127. class PixelId( Id, Position, PixelModifierList, ChannelList ):
  128. '''
  129. Pixel identifier container class
  130. '''
  131. def __init__( self, uid ):
  132. Id.__init__( self )
  133. Position.__init__( self )
  134. PixelModifierList.__init__( self )
  135. ChannelList.__init__( self )
  136. self.uid = uid
  137. self.type = 'Pixel'
  138. def unique_key( self ):
  139. '''
  140. Returns the key string used for datastructure sorting
  141. '''
  142. return "P{0}".format( self.uid )
  143. def __repr__( self ):
  144. # Positions are a special case
  145. if self.positionSet():
  146. return "{0} <= {1}".format( self.unique_key(), self.strPosition() )
  147. extra = ""
  148. if len( self.modifiers ) > 0:
  149. extra += "({0})".format( self.strModifiers() )
  150. if len( self.channels ) > 0:
  151. extra += "({0})".format( self.strChannels() )
  152. return "{0}{1}".format( self.unique_key(), extra )
  153. class PixelLayerId( Id, PixelModifierList ):
  154. '''
  155. Pixel Layer identifier container class
  156. '''
  157. def __init__( self, uid ):
  158. Id.__init__( self )
  159. PixelModifierList.__init__( self )
  160. self.uid = uid
  161. self.type = 'PixelLayer'
  162. def __repr__( self ):
  163. if len( self.modifiers ) > 0:
  164. return "PL{0}({1})".format( self.uid, self.strModifiers() )
  165. return "PL{0}".format( self.uid )
  166. class CapId( Id ):
  167. '''
  168. Capability identifier
  169. '''
  170. def __init__( self, name, type, arg_list=[] ):
  171. '''
  172. @param name: Name of capability
  173. @param type: Type of capability definition, string
  174. @param arg_list: List of CapArgIds, empty list if there are none
  175. '''
  176. Id.__init__( self )
  177. self.name = name
  178. self.type = type
  179. self.arg_list = arg_list
  180. def __repr__( self ):
  181. # Generate prettified argument list
  182. arg_string = ""
  183. for arg in self.arg_list:
  184. arg_string += "{0},".format( arg )
  185. if len( arg_string ) > 0:
  186. arg_string = arg_string[:-1]
  187. return "{0}({1})".format( self.name, arg_string )
  188. def total_arg_bytes( self ):
  189. '''
  190. Calculate the total number of bytes needed for the args
  191. return: Number of bytes
  192. '''
  193. # Zero if no args
  194. total_bytes = 0
  195. for arg in self.arg_list:
  196. total_bytes += arg.width
  197. return total_bytes
  198. class NoneId( CapId ):
  199. '''
  200. None identifier
  201. It's just a capability...that does nothing (instead of infering to do something else)
  202. '''
  203. def __init__( self ):
  204. super().__init__( 'None', 'None' )
  205. def __repr__( self ):
  206. return "None"
  207. class CapArgId( Id ):
  208. '''
  209. Capability Argument identifier
  210. '''
  211. def __init__( self, name, width=None ):
  212. '''
  213. @param name: Name of argument
  214. @param width: Byte-width of the argument, if None, this is not port of a capability definition
  215. '''
  216. Id.__init__( self )
  217. self.name = name
  218. self.width = width
  219. self.type = 'CapArg'
  220. def __repr__( self ):
  221. if self.width is None:
  222. return "{0}".format( self.name )
  223. else:
  224. return "{0}:{1}".format( self.name, self.width )