Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;-------------------------------------------------------------------------------
- ; Transmitter.S - ATtiny85 dual sensor gate buzzer/doorbell transmitter
- ;-------------------------------------------------------------------------------
- ;
- ; Author: Daniel Neville (creamygoat@gmail.com)
- ; Date: 19 December 2014
- ; Licence: Public domain
- ; Version: 1.0
- ;
- ; This transmitter reports the combined status of its two sensor inputs to
- ; one or more receivers which have been taught the secret AES-CMAC key by
- ; the transmitter.
- ;
- ; In addition to the state of the sensors, a pair of sound indices, one for
- ; each sensor, is transmitted with the state. Thus the user can know which
- ; sensor is activated or deactivated. The transmitter's Sound Select buttons,
- ; one for each sensor, allow the user to cycle through the available sounds
- ; to be associated with that sensor.
- ;
- ; The transmission of the secret key is protected by a shared key unless the
- ; self-timer is activated with a long press of the Teach button. (This is
- ; useful if the shared key in EEPROM is corrupted.)
- ;
- ; By default, sensors with normally closed contacts are assumed. A long press
- ; of a Sound Select button inverts the sense of the contacts for the sensor
- ; associated with that button so that sensors with normally open contacts may
- ; be used.
- ;
- ; A very long press of a Sound Select button activates Pinging Mode to assist
- ; with the estimation of the transmitter's range. Pinging Mode stops when a
- ; button is pressed or after ten minutes of pinging.
- ;
- ; The transmitter harvests entropy from the timing of changes of button and
- ; sensor states, slowly mutating random data both in EEPROM and in SRAM.
- ; This data is used to generate the secret AES-CMAC key and the lower 12
- ; bits of the transmitter's serial number when the Teach button is pressed.
- ; Further randomisation of the secret key for successive Teach transmissions
- ; is suppressed until a Sound Select button is pressed or the power is
- ; disconnected.
- ;
- ; The 128 bit (super-secret) shared key used to protect the secret AES-CMAC key
- ; transfer to one or more chimes in Learn Mode is stored in EEPROM at addresses
- ; 2 to 17 inclusive. The rest of the EEPROM need not be initalised to any
- ; particular value.
- ;
- ; Weak pullups are provided on the sensor inputs.
- ;
- ; PIN ASSIGNMENT
- ; ____
- ; ~RESET 1| AT |8 Vcc
- ; SENSOR1 2|tiny|7 ADCBUTTONS
- ; SENSOR2 3| 85 |6 ACTIVITYLED
- ; GND 4|____|5 RADIOTX
- ;
- ; ADC BUTTON WIRING
- ;
- ; Vcc -----*---------------------------
- ; |
- ; R4 [ ]
- ; |
- ; *---------*---------*------> ADCBUTTONS
- ; | | |
- ; R3 [ ] R2 [ ] R1 [ ]
- ; | | | R1 = 6.8k ohms
- ; | o | o | o R2 = 1.8k ohms
- ; TEACH [| SS2 [| SS1 [| R3 = 220 ohms
- ; | o | o | o R4 = 3.0k ohms or 3.3k ohms
- ; | | |
- ; GND -----*---------*---------*------
- ;
- ;
- ; BUTTON FUNCTIONS
- ;
- ; Button Label Press Action
- ;
- ; TEACH TEACH/DELAYED Short Generate a new secret key and transmit the
- ; key to one or more chimes in Learn Mode.
- ; The secret key is encrypted with the fixed,
- ; super-secret shared key.
- ;
- ; Long Generate and transmit without encryption
- ; a new secret key after about ten seconds.
- ; The activity LED will flash in the manner
- ; of a camera's self timer.
- ;
- ; SS1 SOUND1/INVERT1 Short Select the next sound (or set of sounds)
- ; for the primary sensor. Some sound sets
- ; include activation, deactivation and
- ; prolonged activation reminder sounds.
- ; Others have just an activation sound.
- ;
- ; Long Switch between normally open or normally
- ; closed contacts for the primary sensor.
- ;
- ; Extended Activate pinging mode to assist with
- ; radio range estimation.
- ;
- ; SS2 SOUND2/INVERT2 Short Select the next sound (or set of sounds)
- ; for the secondary sensor.
- ;
- ; Long Switch between normally open or normally
- ; closed contacts for the secondary sensor.
- ;
- ; Extended Activate pinging mode to assist with
- ; radio range estimation.
- ;
- ; TRANSMITTED MESSAGES
- ; _ _
- ; The data is Manchester encoded so that 0 = |_ and 1 = _| . The leader pulses
- ; prime the automatic gain control of the receiver and the Manchester-violating
- ; synchronisation pattern low 3, high 3, low 1 appended with a Manchester
- ; encoded 1 indicates the beginning of data. Each data byte is transmitted
- ; MSB first and with a following parity bit so that the parity of all nine bits
- ; is even. There is no special data terminator: The receiver stops listening
- ; once the middle of the last Manchester encoded bit (a parity bit) is received
- ; and the transmission level can be held low the instant the last encoded bit
- ; is sent.
- ;
- ; _ _ _ ___ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
- ; ..._| |_| |_| |___| |__| :_|_:_|_:_|_:_|_:_|_:_|_:_|_:_|_:_|_:_|_:_|_:...
- ; Leader | Synch | 7 6 5 4 3 2 1 0 P | 7 6
- ; | | First byte and even parity bit |
- ;
- ; Command message (14 bytes):
- ; Serial number (4 bytes, big-endian)
- ; Sequence number (4 bytes, big-endian)
- ; Command (1 byte)
- ; Parameter (1 byte)
- ; CMAC (first 4 bytes of the chained cipher in column-major format)
- ;
- ; Commands:
- ; Command Parameter
- ; 000000vu jjjjiiii Sensor states u & v, sound sets i & j
- ; 000001qz 0000iiii Sound test for sensor q in state z, sound set i
- ; 000010qx 000000kk Special sound k for sensor q
- ; k = 0 for +sense, 1 for -sense, 2 for ping
- ;
- ; Teach message (28 bytes):
- ; Serial number (4 bytes, big-endian)
- ; Sequence number (4 bytes, big-endian)
- ; Auxiliary data (2 bytes) - bit 0 of the 2nd byte set => key is unencrypted
- ; CMAC Key (16 bytes, column major)
- ; CRC-CCITT (2 bytes, big-endian so that the CRC of all 28 bytes is zero.)
- ;
- ; EXAMPLE EEPROM IMAGE
- ;
- /*
- :200000002FFF337C8BE33D17576A5F7D06C8FF7677BABC1A0000FFFFB68BEB75C758988D77
- :200020002469350721BCFB2FDC0C8C273C16DD4A1150C91A6CBB33AB6F2172C965085C827D
- :20004000E158A879C609FB9FCEB98FBB7CE90DB17EFF9C5477DEE447AF92F534995D0C810F
- :200060001C1DC1F84F584982777777777777777777777777777777777777777777777777F4
- :20008000777777777777777777777777777777777777777777777777777777777777777780
- :2000A0007777777777777777777777777777777777777777777777771100000011000000F6
- :2000C000110000001100000011000000110000001100000011000000110000001100000098
- :2000E000110000001100000011000000110000001100000011000000110000001100000078
- :20010000110000001100000011000000110000001100000011000000110000001100000057
- :20012000110000001100000011000000110000001100000011000000110000001100000037
- :20014000110000001100000011000000110000001100000011000000110000001100000017
- :200160001100000011000000110000001100000011000000110000001100000011000000F7
- :200180001100000011000000110000001100000011000000110000001100000011000000D7
- :2001A0001100000011000000110000001100000011000000110000001100000011000000B7
- :2001C000110000001100000011000000110000001100000011000000110000001100000097
- :2001E000110000001100000011000000110000001100000011000000FFFFFFFFFFFFFFFFA1
- :00000001FF
- */
- ;
- ;-------------------------------------------------------------------------------
- ; Notes
- ;-------------------------------------------------------------------------------
- ;
- ; Fuses:
- ; Low fuse: 0xe2 (4:SUT0, 3-0:CKSEL=8MHz)
- ; High fuse: 0xdf (5:SPIEN) 0xd7 (6:SPIEN, 3:EESAVE)
- ; Extended fuse: 0xff
- ;
- ; Fuse programming
- ; avrdude -p t85 -c usbasp -U lfuse:w:0xe2:m
- ; avrdude -p t85 -c usbasp -U hfuse:w:0xd7:m
- ; avrdude -p t85 -c usbasp -U efuse:w:0xfe:m
- ;
- ; Compiling, inspecting and programming:
- ;
- ; avr-gcc -mmcu=attiny85 -o Transmitter.o Transmitter.S
- ; avr-objdump -C -d Transmitter.o
- ; avr-ld -o Transmitter.elf Transmitter.o
- ; avr-objcopy -O ihex Transmitter.elf Transmitter.hex
- ; avrdude -p t85 -c usbasp -U flash:w:Transmitter.hex:i
- ; avrdude -p t85 -c usbasp -U eeprom:w:Transmitter.eep:i
- ;
- ; Key generation:
- ;
- ; head </dev/random -c 16|hexdump -v -e '/1 "%02X"'; echo
- ;
- ;-------------------------------------------------------------------------------
- ; Imports
- ; Exports
- ; Constants
- ; Structures
- ; EEPROM addresses
- ; Macros
- ;
- ; Interrupt handlers
- ;
- ; Basic routines
- ; Xor16B
- ; Copy16B
- ; Copy8B
- ; DelayNCycles
- ; Delay10Cycles
- ; Delay8Cycles
- ; CalculateCRC_CCITT
- ; DebounceSensor
- ;
- ; EEPROM routines
- ; ReadEEPROMByte
- ; ReadEEPROMBlock
- ; WriteEEPROMByte
- ; WriteEEPROMBlock
- ;
- ; AES routines
- ; AES_SubstituteAndShift
- ; AES_MixColumn
- ; AES_AdvanceRoundKey
- ; AES_AdvanceCMACSubKey
- ; AES_Encrypt
- ;
- ; Application routines
- ; FindCurrentEWLDataSlot
- ; LazilyUpdateEWLData
- ; FullyUpdateEWLData
- ; MutateRandomData
- ; RandomiseCMACKey
- ; BuildTeachMessage
- ;
- ; Initialisation
- ; InitialiseRegisterConstants
- ; InitialiseHardware
- ; ClearGlobals
- ; LoadEverythingFromEEPROM
- ;
- ; main
- ; main_Loop
- ; main_Synchronise
- ; main_Update32kHzCounter
- ; main_UpdateTransmitPin
- ; main_TimeShare32By8
- ; main_T0_TransmitPacket
- ; main_TxState_Idle
- ; main_TxState_Begin
- ; main_TxState_Sync
- ; main_TxState_Data
- ; main_TxState_Data_Bit
- ; main_TxState_Data_Parity
- ; main_TxState_Data_ModulateBit
- ; main_TxState_Terminator
- ; main_TxState_Rest
- ; main_Tx_BufferMarkSpace
- ; main_T1_Authentication
- ; main_AES_Mixcolumn
- ; main_AES_SubAndShift
- ; main_AES_AddRoundKey
- ; main_AES_AdvanceRoundKey
- ; main_AES_AdvanceRoundKey_RudeEntryForRound10
- ; main_AES_StartEncryption
- ; main_AES_IdleOrStartAES
- ; main_AES_Idle
- ; main_Auth_Idle
- ; main_Auth_CmdMsg_XorK2
- ; main_Auth_CmdMsg_LoadK
- ; main_Auth_K2_Begin
- ; main_Auth_K2_Clear
- ; main_AES_Finished
- ; main_Auth_K2_GenK1
- ; main_Auth_K2_GenK2
- ; main_Auth_End
- ; main_Auth_CmdMsg_Begin
- ; main_Auth_CmdMsg_WriteCMAC
- ; main_Copy16BAndLoop
- ; main_T2_TeachAndSoundSelectTasks
- ; main_T2_TASSTasks_T0_ADCInputAndTASSTimers
- ; main_T2_TASSTasks_T1_ButtonLogic
- ; main_T2_TASSTasks_T2_SaveAndTransmit
- ; main_T2_TASSTasks_T3
- ; main_T3_SensorInputConditioningAndEntropyHarvesting
- ; main_T4_SensorStateTxBurstsAndEWLUpdates
- ; main_T5_RefreshEEPROM
- ; main_T6
- ; main_T7
- ;
- ; Data in program memory
- ;
- ; PM_AES_SBox
- ;
- ; Globals in SRAM
- ; TxRunLengthsRingBuffer
- ; AES_Matrix_M
- ; AES_Matrix_K
- ; AES_Matrix_W
- ; AuthenticationData
- ; EWLState
- ; EntropyHarvester
- ;-------------------------------------------------------------------------------
- ; Imports
- ;-------------------------------------------------------------------------------
- #include <avr/common.h>
- #include <avr/io.h>
- ;-------------------------------------------------------------------------------
- ; Exports
- ;-------------------------------------------------------------------------------
- .global main
- .global __vector_default
- ;-------------------------------------------------------------------------------
- ; Constants
- ;-------------------------------------------------------------------------------
- ; Inputs and outputs
- OUTPUT_BIT_RADIO = 0
- OUTPUT_BIT_ACTIVITY_LED = 1
- INPUT_BIT_BUTTONS = 2
- INPUT_BIT_PRIMARY_SENSOR = 3
- INPUT_BIT_SECONDARY_SENSOR = 4
- BUTTONS_DIGITAL_INPUT_DISABLE_BIT = ADC1D; ADC1 is on Port B bit 2 (pin 7).
- BUTTONS_ADC_MUX_SELECTOR = 0b0001 ; 00xx = ADCn in single-ended mode.
- ; Sensor debounce times in quarter-milliseconds, up to 127 (31.75ms)
- SENSOR_DB_DELAY_CONTACTS_CLOSED = 234 ; 60ms
- SENSOR_DB_DELAY_CONTACTS_OPEN = 156 ; 40ms
- ; Button debounce times in milliseconds, up to 255 (0.255 seconds)
- BUTTON_DB_DELAY_ADC = 65 ; 65ms
- ; Teach and Sound Select times in multiples of 64 milliseconds
- TEACH_BUTTON_LONG_PRESS_TIME = 31 ; 2 seconds
- SOUND_SELECT_BUTTON_LONG_PRESS_TIME = 47 ; 3 seconds
- SOUND_SELECT_BUTTON_VERY_LONG_PRESS_TIME = 125 ; 8 seconds
- ACTIVATION_SOUND_TO_DEACTIVATION_SOUND_DELAY = 31 ; 2 seconds
- SENSE_INVERSION_DELAY = 23 ; 1.5 seconds
- PING_START_DELAY = 16 ; 1 second
- PING_INTERVAL_DOUBLED = 125 ; 8 seconds (a ping every 4 seconds)
- ; Transmitter signal timing in 32kHz ticks
- TX_TIME_UNIT = 4 ; Minimum is 4, good for 8000 baud
- TX_RLB_REST_TIME = 240; Last entry to put in the run length buffer
- TX_TASK_REST_TIME = 200; 50ms in 4kHz ticks
- TX_NUMBER_OF_LEADER_PULSES = 24
- ; Ring buffer for run lengths of the transmit pin state
- TX_RING_BUFFER_INDEX_BITS = 4
- TX_RING_BUFFER_INDEX_RANGE = 1 << TX_RING_BUFFER_INDEX_BITS
- TX_RING_BUFFER_INDEX_MASK = TX_RING_BUFFER_INDEX_RANGE - 1
- ; Transmitter state
- TX_STATE_IDLE = 0
- TX_STATE_BEGIN = 1
- TX_STATE_SYNC = 2
- TX_STATE_DATA = 3
- TX_STATE_TERMINATOR = 4
- TX_STATE_REST = 5
- ; State for AES-CMAC message authenticator
- AUTH_STATE_IDLE = 0
- AUTH_STATE_CMDMSG_BEGIN = 1
- AUTH_STATE_CMDMSG_LOAD_K = 2
- AUTH_STATE_CMDMSG_XOR_K2 = 3
- AUTH_STATE_CMDMSG_CMAC = 4
- AUTH_STATE_K2_BEGIN = 5
- AUTH_STATE_K2_CLEAR = 6
- AUTH_STATE_K2_GEN_K1 = 7
- AUTH_STATE_K2_GEN_K2 = 8
- ; Important states for AES encrpytion
- AES_STATE_IDLE = 0xFF
- AES_STATE_BEGIN = 0xA2
- AES_STATE_FINISHED = 0x00
- ; Task flag bits, set 1
- bTASK1_SEND_CMD_MESSAGE = 0
- bTASK1_SEND_TEACH_MESSAGE = 1
- bTASK1_SAVE_SOUND_INDICES = 2
- bTASK1_SEND_PRIMARY_SOUND_A = 4
- bTASK1_SEND_PRIMARY_SOUND_B = 5
- bTASK1_SEND_SECONDARY_SOUND_A = 6
- bTASK1_SEND_SECONDARY_SOUND_B = 7
- ; Task flag masks, set 1
- mTASK1_SEND_CMD_MESSAGE = 1 << bTASK1_SEND_CMD_MESSAGE
- mTASK1_SEND_TEACH_MESSAGE = 1 << bTASK1_SEND_TEACH_MESSAGE
- mTASK1_SAVE_SOUND_INDICES = 1 << bTASK1_SAVE_SOUND_INDICES
- mTASK1_SEND_PRIMARY_SOUND_A = 1 << bTASK1_SEND_PRIMARY_SOUND_A
- mTASK1_SEND_PRIMARY_SOUND_B = 1 << bTASK1_SEND_PRIMARY_SOUND_B
- mTASK1_SEND_SECONDARY_SOUND_A = 1 << bTASK1_SEND_SECONDARY_SOUND_A
- mTASK1_SEND_SECONDARY_SOUND_B = 1 << bTASK1_SEND_SECONDARY_SOUND_B
- ; Task flag bits, set 2
- bTASK2_SEND_PRIMARY_SENSE_NORMAL = 0
- bTASK2_SEND_PRIMARY_SENSE_INVERTED = 1
- bTASK2_SEND_SECONDARY_SENSE_NORMAL = 2
- bTASK2_SEND_SECONDARY_SENSE_INVERTED = 3
- bTASK2_SAVE_SENSOR_ACTIVATION_SENSES = 4
- bTASK2_SEND_PING = 5
- ; Task flag masks, set 2
- mTASK2_SEND_PRIMARY_SENSE_NORMAL = 1 << bTASK2_SEND_PRIMARY_SENSE_NORMAL
- mTASK2_SEND_PRIMARY_SENSE_INVERTED = 1 << bTASK2_SEND_PRIMARY_SENSE_INVERTED
- mTASK2_SEND_SECONDARY_SENSE_NORMAL = 1 << bTASK2_SEND_SECONDARY_SENSE_NORMAL
- mTASK2_SEND_SECONDARY_SENSE_INVERTED = 1 << bTASK2_SEND_SECONDARY_SENSE_INVERTED
- mTASK2_SAVE_SENSOR_ACTIVATION_SENSES = 1 << bTASK2_SAVE_SENSOR_ACTIVATION_SENSES
- mTASK2_SEND_PING = 1 << bTASK2_SEND_PING
- ; Slow clock bits
- bCLOCK_CMD_MSG_BURST = 0
- bCLOCK_TASS = 1
- bCLOCK_EEPROM_REFRESH = 2
- ; Teach and Sound Select states
- TASS_STATE_IDLE = 0
- TASS_STATE_TEACH_PRESSED = 1
- TASS_STATE_TEACH_LONG_PRESSED = 2
- TASS_STATE_DELAYED_TEACH = 3
- TASS_STATE_SILLY_WALK_FOR_PING = 4
- TASS_STATE_PINGING = 5
- TASS_STATE_WAIT_FOR_RELEASE = 6
- ; Entropy harvesting data mutation
- ; 6 bits for the mutation index is the minimum needed to maintain the purity
- ; of the CMAC key and to provide auxiliary random data.
- EH_MUTATION_INDEX_BITS = 6
- EH_MUTATION_INDEX_RANGE = 1 << EH_MUTATION_INDEX_BITS
- EH_MUTATION_INDEX_MASK = EH_MUTATION_INDEX_RANGE - 1
- EH_MUTATION_INDEX_ADVANCE = 23
- EH_AUX_RANDOM_DATA_START_INDEX = 32 ; Clear of the CMAC stuff.
- EH_UPDATE_INDEX_ADVANCE = 1
- EH_UPDATE_COUNTER_BITS = 1
- ; EEPROM wear levelling
- EWL_COUNTS_BETWEEN_WRITES = 8
- EWL_INDEX_RANGE = 80
- EWL_DATA_SLOT_SIZE = 4
- EWL_DATA_RING_SIZE = EWL_INDEX_RANGE * EWL_DATA_SLOT_SIZE
- ;-------------------------------------------------------------------------------
- ; Structures
- ;-------------------------------------------------------------------------------
- ; Command message (big endian)
- CmdMsg_SerialNumber = 0
- CmdMsg_SequenceNumber = 4
- CmdMsg_Command = 8
- CmdMsg_Parameter = 9
- CmdMsg_CMAC = 10
- CmdMsgSize = 14
- ; Teach message (big-endian)
- TeachMsg_SerialNumber = 0
- TeachMsg_SequenceNumber = 4
- TeachMsg_AuxData = 8
- TeachMsg_EncryptedCMACKey = 10
- TeachMsg_MessageCRC = 26
- TeachMsgSize = 28
- ; Packet size constants
- TX_COMMAND_PACKET_LENGTH = CmdMsgSize
- TX_TEACH_PACKET_LENGTH = TeachMsgSize
- .ifgt TX_TEACH_PACKET_LENGTH - TX_COMMAND_PACKET_LENGTH
- TX_MAX_PACKET_LENGTH = TeachMsgSize
- .else
- TX_MAX_PACKET_LENGTH = CmdMsgSize
- .endif
- ; Transmit run length buffer state
- TxBit_HeadIx = 0
- TxBit_TailIx = 1
- TxBitSize = 2
- ;Transmitter
- Tx_State = 0
- Tx_Counter = 1
- Tx_NumBytesSent = 2
- Tx_NumBytesToSend = 3
- Tx_Parity = 4
- Tx_ShiftRegister = 5
- Tx_TxBit = 6
- Tx_Data = Tx_TxBit + TxBitSize
- TxSize = Tx_Data + TX_MAX_PACKET_LENGTH
- ; EEPROM wear levelling state (kept in SRAM)
- EWLS_SlotIndex = 0
- EWLS_SlotValue = 1
- EWLS_UpdateCountdown = 2
- EWLS_NumBytesToWrite = 3
- EWLS_NewSequenceNumber = 4
- EWLSSize = 8
- ; Entropy harvester
- EH_MutationIndex = 0
- EH_MutationCounter = 1
- EH_EEPROMUpdateIndex = 2
- EH_EEPROMUpdatePending = 3
- EH_RandomData = 4
- EHSize = EH_RandomData + EH_MUTATION_INDEX_RANGE
- ; Authentication data
- AD_SerialNumber = 0
- AD_SequenceNumber = 4
- AD_CMACKey = 8
- AD_CMACSubkeyK2 = 24
- AD_HaveK2 = 40
- ADSize = 41
- ; Analogue to Digital Converter buttons
- ADCB_MutexState = 0
- ADCB_State = 1
- ADCB_ProvisionalState = 2
- ADCB_AcceptanceCountdown = 3
- ADCBSize = 4
- ; Teach and sound select buttons
- TASS_TeachOrPingState = 0
- TASS_LastButtonsState = 1
- TASS_LongPressCountdown = 2
- TASS_NewSensorActivationSenses = 3
- TASS_Sensor1InversionCountdown = 4
- TASS_Sensor2InversionCountdown = 5
- TASS_SS1LongPressCountdown = 6
- TASS_SS2LongPressCountdown = 7
- TASS_PrimarySoundTestCountdown = 8
- TASS_SecondarySoundTestCountdown = 9
- TASS_NumTeachMessagesToSend = 10
- TASS_SuppressKeyRandomisation = 11
- TASS_SuppressKeyEncryption = 12
- TASS_NumPingsToSend = 13
- TASS_PingIntervalCountdown = 14
- TASSSize = 15
- ; Globals
- G_CurrentTimer0Match = 0
- G_SlowClocks = 1
- G_SoundIndices = 2
- G_SensorActivationSenses = 3
- G_TaskFlags1 = 4
- G_TaskFlags2 = 5
- G_PrimarySensorIntegral = 6
- G_SecondarySensorIntegral = 7
- G_SensorsState = 8
- G_TransmittedSensorsState = 9
- G_AuthenticationState = 10
- G_AESState = 11
- G_AESRoundConstantByte = 12
- G_LastADCButtonsState = 13
- G_CmdTxDelayRandomByte = 14
- G_CmdTxNumRepeatsToSend = 15
- G_CmdTxRepeatSchedule = 16
- G_EEPROMRefreshCounter = G_CmdTxRepeatSchedule + 8
- G_ADCButtons = G_EEPROMRefreshCounter + 2
- G_EWLState = G_ADCButtons + ADCBSize
- G_Transmitter = G_EWLState + EWLSSize
- GSize = G_Transmitter + TxSize
- ;-------------------------------------------------------------------------------
- ; EEPROM addresses
- ;-------------------------------------------------------------------------------
- EEPROM_InvSoundIndices = 0
- EEPROM_SensorActivationSenses = 1
- EEPROM_SharedKey = 2
- EEPROM_SerialNumber = 18
- EEPROM_CMACKey = 24
- EEPROM_RandomData = 40
- EEPROM_EWLStatusRing = EEPROM_RandomData + EH_MUTATION_INDEX_RANGE
- EEPROM_EWLDataRing = EEPROM_EWLStatusRing + EWL_INDEX_RANGE
- EEPROM_EWLDataRingEnd = EEPROM_EWLDataRing + EWL_DATA_RING_SIZE
- EEPROM_End = EEPROM_EWLDataRingEnd
- .ifgt EEPROM_End - 512
- .error "There is not enough space in the EEPROM."
- .endif
- ;-------------------------------------------------------------------------------
- ; Macros
- ;-------------------------------------------------------------------------------
- ; Conditional execution of the following one-word instruction
- .macro ifcc
- brcs . + 2
- .endm
- .macro ifcs
- brcc . + 2
- .endm
- .macro ifne
- breq . + 2
- .endm
- .macro ifeq
- brne . + 2
- .endm
- .macro ifpl
- brmi . + 2
- .endm
- .macro ifmi
- brpl . + 2
- .endm
- .macro ifvc
- brvs . + 2
- .endm
- .macro ifvs
- brvc . + 2
- .endm
- .macro iflt
- brge . + 2
- .endm
- .macro ifge
- brlt . + 2
- .endm
- .macro ifhc
- brhs . + 2
- .endm
- .macro ifhs
- brhc . + 2
- .endm
- .macro iftc
- brts . + 2
- .endm
- .macro ifts
- brtc . + 2
- .endm
- .macro ifid
- brie . + 2
- .endm
- .macro ifie
- brid . + 2
- .endm
- .macro iflo
- brsh . + 2
- .endm
- .macro ifsh
- brlo . + 2
- .endm
- .macro ifbs
- brbc . + 2
- .endm
- .macro ifbc
- brbs . + 2
- .endm
- ;-------------------------------------------------------------------------------
- ; Positive-sense register and I/O bit tests
- .macro ifbrc a:req, b:req
- sbrs \a, \b
- .endm
- .macro ifbrs a:req, b:req
- sbrc \a, \b
- .endm
- .macro ifbic a:req, b:req
- sbis \a, \b
- .endm
- .macro ifbis a:req, b:req
- sbic \a, \b
- .endm
- ;-------------------------------------------------------------------------------
- ; Load high & low 8-bit registers with one 16-bit word
- .macro ldhl a:req, b:req, c:req
- ldi \b, lo8(\c)
- ldi \a, hi8(\c)
- .endm
- ;-------------------------------------------------------------------------------
- ; Load immediate word
- .macro ldiw a:req, b:req
- .ifc \a, r17:r16
- ldhl r17, r16, \b
- .else
- .ifc \a, r19:r18
- ldhl r19, r18, \b
- .else
- .ifc \a, r21:r20
- ldhl r21, r20, \b
- .else
- .ifc \a, r23:r22
- ldhl r23, r22, \b
- .else
- .ifc \a, r25:r24
- ldhl r25, r24, \b
- .else
- .ifc \a, r27:r26
- ldhl XH, XL, \b
- .else
- .ifc \a, r29:r28
- ldhl YH, YL, \b
- .else
- .ifc \a, r31:r30
- ldhl ZH, ZL, \b
- .else
- .ifc \a, X
- ldhl XH, XL, \b
- .else
- .ifc \a, Y
- ldhl YH, YL, \b
- .else
- .ifc \a, Z
- ldhl ZH, ZL, \b
- .else
- .error "Expected LDIW R, x where R is X, Y, Z or a register pair."
- .endif
- .endif
- .endif
- .endif
- .endif
- .endif
- .endif
- .endif
- .endif
- .endif
- .endif
- .endm
- ;-------------------------------------------------------------------------------
- .section .text
- ;-------------------------------------------------------------------------------
- ;-------------------------------------------------------------------------------
- ; Interrupt handlers
- ;-------------------------------------------------------------------------------
- __vector_default:
- reti
- ;-------------------------------------------------------------------------------
- ; Basic routines
- ;-------------------------------------------------------------------------------
- Xor16B:
- ; In: Z = key
- ; X = state
- ld r0, X
- ldd r7, Z + 0
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 1
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 2
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 3
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 4
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 5
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 6
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 7
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 8
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 9
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 10
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 11
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 12
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 13
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 14
- eor r0, r7
- st X+, r0
- ld r0, X
- ldd r7, Z + 15
- eor r0, r7
- st X+, r0
- ; 112 cycles
- ret
- ;-------------------------------------------------------------------------------
- Copy16B:
- ; In: Z = source
- ; X = destination
- 1: ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- Copy8B:
- com r1
- brne 1b
- ; 2(35)-1 = 69 cycles
- ret
- ;-------------------------------------------------------------------------------
- DelayNCycles:
- ; In: r24 = Number of cycles to delay, including the time taken to call
- ; A precise delay is possible for 28..255 cycles. 15 cycles is the minimum.
- cpi r24, 28
- brcc 3f
- cpi r24, 16
- brcs 2f
- subi r24, 12
- nop
- lsr r24
- lsr r24
- 1: nop
- dec r24
- brne 1b
- ret
- 2: nop
- nop
- ret
- 3: subi r24, 24
- mov r22, r24
- com r22
- andi r22, 3
- lsr r24
- lsr r24
- ldiw Z, 4f
- lsr ZH
- ror ZL
- add ZL, r22
- adc ZH, r1
- ijmp
- 4: nop
- nop
- nop
- 5: nop
- dec r24
- brne 5b
- ret
- ;-------------------------------------------------------------------------------
- Delay10Cycles:
- nop
- nop
- Delay8Cycles:
- ret
- ;-------------------------------------------------------------------------------
- DebounceSensor:
- ; In: r24: Debounce state (0: released, 1..254: uncertain 255: pressed)
- ; r22: Raw input (0: released, 1..255: pressed)
- ; Out: r24: Updated debounce state to use in Schmitt trigger logic
- tst r22
- breq 1f
- nop
- cpi r24, 255 - SENSOR_DB_DELAY_CONTACTS_CLOSED
- ifcs
- ldi r24, 255 - SENSOR_DB_DELAY_CONTACTS_CLOSED
- add r24, r2
- sbc r24, r1
- ret
- 1: cpi r24, SENSOR_DB_DELAY_CONTACTS_OPEN
- ifcc
- ldi r24, SENSOR_DB_DELAY_CONTACTS_OPEN
- sub r24, r2
- adc r24, r1
- 4: ret
- ; 16 cycles, including call
- ;-------------------------------------------------------------------------------
- CalculateCRC_CCITT:
- ; In: X = Data to checksum
- ; r17:r16 = number of bytes
- ; Out: X = End of data
- ; r17:r16 = CRC
- ; If the resulting 16-bit checksum is appended to the data high-byte first,
- ; the CRC of augmented data will be zero.
- clr r7
- inc r7
- mov r8, r16
- mov r9, r17
- ser r16
- ser r17
- ldi r18, 0x21
- ldi r19, 0x10
- 1: ld r0, X+
- eor r17, r0
- com r1
- 2: lsl r16
- rol r17
- brcc 3f
- eor r16, r18
- eor r17, r19
- 3: lsr r1
- brne 2b
- sub r8, r7
- sbc r9, r1
- brne 1b
- ret
- ;-------------------------------------------------------------------------------
- ; EEPROM routines
- ;-------------------------------------------------------------------------------
- ReadEEPROMByte:
- ; In: X = address in EEPROM
- ; Out: r0 = byte
- sbic _SFR_IO_ADDR(EECR), EEPE
- rjmp . - 4
- out _SFR_IO_ADDR(EEARH), XH
- out _SFR_IO_ADDR(EEARL), XL
- sbi _SFR_IO_ADDR(EECR), EERE
- in r0, _SFR_IO_ADDR(EEDR)
- ret
- ; 18 cycles including call and 4 cycle CPU halt, if EEPROM was ready
- ;-------------------------------------------------------------------------------
- ReadEEPROMBlock:
- ; In: X = source in EEPROM
- ; Z = destination in SRAM
- ; r16 = number of bytes to read
- tst r16
- breq 2f
- 1: rcall ReadEEPROMByte
- adiw XL, 1
- st Z+, r0
- dec r16
- brne 1b
- 2: ret
- ;-------------------------------------------------------------------------------
- WriteEEPROMByte:
- ; In: X = address in EEPROM
- ; r0 = byte to write
- push r16
- ldi r16, (0 << EEPM1) | (0 << EEPM0) ; Erase and write
- sbic _SFR_IO_ADDR(EECR), EEPE
- rjmp . - 4
- out _SFR_IO_ADDR(EECR), r16
- out _SFR_IO_ADDR(EEARH), XH
- out _SFR_IO_ADDR(EEARL), XL
- out _SFR_IO_ADDR(EEDR), r0
- sbi _SFR_IO_ADDR(EECR), EEMPE
- sbi _SFR_IO_ADDR(EECR), EEPE
- pop r16
- ret
- ; 23 cycles including call and 2 cycle CPU halt, if EEPROM was ready
- ;-------------------------------------------------------------------------------
- WriteEEPROMBlock:
- ; In: X = destination in EEPROM
- ; Z = source in SRAM
- ; r16 = number of bytes to write
- tst r16
- breq 2f
- 1: ld r0, Z+
- rcall WriteEEPROMByte
- adiw XL, 1
- dec r16
- brne 1b
- 2: ret
- ;-------------------------------------------------------------------------------
- ; AES routines
- ;-------------------------------------------------------------------------------
- AES_SubstituteAndShift:
- ; In: Y = address of 4x4 byte column-major state
- ldi ZH, hi8(PM_AES_SBox)
- ; First row
- ldd ZL, Y + 0
- lpm r8, Z
- ldd ZL, Y + 4
- lpm r9, Z
- ldd ZL, Y + 8
- lpm r10, Z
- ldd ZL, Y + 12
- lpm r11, Z
- std Y + 0, r8
- std Y + 4, r9
- std Y + 8, r10
- std Y + 12, r11
- ; Second row
- ldd ZL, Y + 1
- lpm r8, Z
- ldd ZL, Y + 5
- lpm r9, Z
- ldd ZL, Y + 9
- lpm r10, Z
- ldd ZL, Y + 13
- lpm r11, Z
- std Y + 1, r9
- std Y + 5, r10
- std Y + 9, r11
- std Y + 13, r8
- ; Third row
- ldd ZL, Y + 2
- lpm r8, Z
- ldd ZL, Y + 6
- lpm r9, Z
- ldd ZL, Y + 10
- lpm r10, Z
- ldd ZL, Y + 14
- lpm r11, Z
- std Y + 2, r10
- std Y + 6, r11
- std Y + 10, r8
- std Y + 14, r9
- ; Fourth row
- ldd ZL, Y + 3
- lpm r8, Z
- ldd ZL, Y + 7
- lpm r9, Z
- ldd ZL, Y + 11
- lpm r10, Z
- ldd ZL, Y + 15
- lpm r11, Z
- std Y + 3, r11
- std Y + 7, r8
- std Y + 11, r9
- std Y + 15, r10
- ; 1 + 4(28) = 113 cycles
- ret
- ;-------------------------------------------------------------------------------
- AES_MixColumn:
- ; In: X = address of column in 4x4 byte column-major state
- ldi r16, 0x1b
- ld r8, X+
- ld r9, X+
- ld r10, X+
- ld r11, X+
- ; Fourth element [3 1 1 2]
- mov r7, r9
- eor r7, r10
- ; gmul2
- mov r0, r11
- lsl r0
- ifcs
- eor r0, r16
- eor r7, r0
- ; gmul3
- mov r0, r8
- lsl r0
- ifcs
- eor r0, r16
- eor r0, r8
- eor r7, r0
- st -X, r7
- ; Third element [1 1 2 3]
- mov r7, r8
- eor r7, r9
- ; gmul2
- mov r0, r10
- lsl r0
- ifcs
- eor r0, r16
- eor r7, r0
- ; gmul3
- mov r0, r11
- lsl r0
- ifcs
- eor r0, r16
- eor r0, r11
- eor r7, r0
- st -X, r7
- ; Second element [1 2 3 1]
- mov r7, r8
- eor r7, r11
- ; gmul2
- mov r0, r9
- lsl r0
- ifcs
- eor r0, r16
- eor r7, r0
- ; gmul3
- mov r0, r10
- lsl r0
- ifcs
- eor r0, r16
- eor r0, r10
- eor r7, r0
- st -X, r7
- ; First element [2 3 1 1]
- mov r7, r10
- eor r7, r11
- ; gmul2
- mov r0, r8
- lsl r0
- ifcs
- eor r0, r16
- eor r7, r0
- ; gmul3
- mov r0, r9
- lsl r0
- ifcs
- eor r0, r16
- eor r0, r9
- eor r7, r0
- st -X, r7
- ; 8 + 4(15) = 68 cycles
- ret
- ;-------------------------------------------------------------------------------
- AES_AdvanceRoundKey:
- ; In: Y = key
- ; r24 = most significant byte of the round constant
- ldi ZH, hi8(PM_AES_SBox)
- ldd ZL, Y + 13
- lpm r8, Z
- eor r8, r24
- ldd ZL, Y + 14
- lpm r9, Z
- ldd ZL, Y + 15
- lpm r10, Z
- ldd ZL, Y + 12
- lpm r11, Z
- 1: ld r0, Y
- eor r8, r0
- st Y+, r8
- ld r0, Y
- eor r9, r0
- st Y+, r9
- ld r0, Y
- eor r10, r0
- st Y+, r10
- ld r0, Y
- eor r11, r0
- st Y+, r11
- ld r0, Y
- eor r8, r0
- st Y+, r8
- ld r0, Y
- eor r9, r0
- st Y+, r9
- ld r0, Y
- eor r10, r0
- st Y+, r10
- ld r0, Y
- eor r11, r0
- st Y+, r11
- com r1
- brne 1b
- ; 22 + 2(43)-1 = 107
- ret
- ;-------------------------------------------------------------------------------
- AES_AdvanceCMACSubKey:
- ; In: X = Either an AES-encrypted block of zeros or the
- ; result of a previous call to this routine
- ; Out: Z = Output
- ; This routine is for generating the subkeys K1 and K2 from
- ; an encryption key K. First, a block of zeros is encrypted
- ; with K and advanced with this routine to yield K1. Calling
- ; this routine a second time yields K2. AES in the CMAC mode
- ; of operation requires the last block in the chained cipher
- ; to be XORed with K1 or K2 before that block is encrypted.
- ; If the message occupies all 128 bits in the last block, K1
- ; is used, otherwise the message is appended with padding
- ; consisting of a bit 1 followed by as many bit zeros as will
- ; fit and K2 is used instead.
- adiw ZL, 15
- adiw XL, 15
- ld r7, X
- lsl r7
- ldi r16, 3
- 1: ld r0, -X
- rol r0
- st -Z, r0
- ld r0, -X
- rol r0
- st -Z, r0
- ld r0, -X
- rol r0
- st -Z, r0
- ld r0, -X
- rol r0
- st -Z, r0
- ld r0, -X
- rol r0
- st -Z, r0
- dec r16
- brne 1b
- ldi r16, 0x87
- ifcs
- eor r7, r16
- std Z + 15, r7
- ; 8 + 3(28)-1 + 5 = 96 cycles
- ret
- ;-------------------------------------------------------------------------------
- AES_Encrypt:
- ; In: Z = key
- ; X = state
- ; r25:24 = subkey working space (16 bytes)
- push YH
- push YL
- movw r20, r24
- movw r22, XL
- ; W := K
- movw XL, r20
- rcall Copy16B ; (Z, X)
- ; Preprocessing step
- movw ZL, r20
- movw XL, r22
- rcall Xor16B ; (Z, X)
- ldi r18, 10
- ldi r19, 0x8D
- 1: movw YL, r22
- rcall AES_SubstituteAndShift ; (Y)
- dec r18
- breq 2f
- movw XL, r22
- rcall AES_MixColumn ; (X)
- adiw XL, 4
- rcall AES_MixColumn ; (X)
- adiw XL, 4
- rcall AES_MixColumn ; (X)
- adiw XL, 4
- rcall AES_MixColumn ; (X)
- 2: movw YL, r20
- ldi r16, 0x1B
- lsl r19
- ifcs
- eor r19, r16
- mov r24, r19
- rcall AES_AdvanceRoundKey ; (Y, r24)
- movw ZL, r20
- movw XL, r22
- rcall Xor16B ; (Z, X)
- tst r18
- brne 1b
- pop YL
- pop YH
- ret
- ;-------------------------------------------------------------------------------
- ; Application routines
- ;-------------------------------------------------------------------------------
- FindCurrentEWLDataSlot:
- ; In: X = Status ring in EEPROM
- ; Z = Data ring in EEPROM
- ; Out: r16 = Index of current slot
- ; r17 = Slot status value
- ; Z = Address of current slot in EPPROM
- ; This routine implements a variation of Atmel's recommendation. The data
- ; (4 bytes in our case) is read from a slot in the Data Ring and written to
- ; a different slot in that ring each time. The parallel Status Ring, filled
- ; with values decreasing by one going backwards in memory indicates which
- ; slot index is the current one: Where a decrement of one fails to occur
- ; indicates the boundary between the current slot index and the next slot
- ; index to use. (if S[(i - 1) mod N] != S[i] - 1, the current slot index is i
- ; and the next slot index to use is (i - 1) mod N. Backwards counting is used
- ; to minimise EEPROM wear and backwards traversal is to make the loop
- ; termination easy. The EEPROM does not need to have any particular initial
- ; state for this routine to work.
- ; Traverse both the status and data rings backwards from the end, with
- ; a previous status value taken from the first item in the status ring.
- ldiw r17:r16, EWL_DATA_RING_SIZE - EWL_DATA_SLOT_SIZE
- add ZL, r16
- adc ZH, r17
- rcall ReadEEPROMByte ; (X)
- mov r17, r0 ; Previous value
- clr r16 ; Previous index
- ; Go backward from the last index.
- ldi r18, EWL_INDEX_RANGE - 1 ; Current index
- add XL, r18
- adc ZH, r1
- 1: rcall ReadEEPROMByte ; (X)
- mov r19, r0 ; Current value
- mov r20, r17 ; Compare with previous value.
- sub r20, r19
- cpi r20, 1
- brne 2f ; A discontinuity! Return the previous index.
- movw r16, r18 ; The previous index and value is now current.
- sbiw XL, 1
- sbiw ZL, EWL_DATA_SLOT_SIZE
- dec r18
- brne 1b
- 2: ret
- ;-------------------------------------------------------------------------------
- LazilyUpdateEWLData:
- ; Monitor the sequence number changes-until-update countdown and update the
- ; EEPROM Wear Levelling data both in SRAM and in EEPROM.
- clr r1 ; Just to be sure
- ldd r17, Y + G_EWLState + EWLS_NumBytesToWrite
- tst r17
- brne 1f
- ; No EWL updating is in progress.
- ; See if the EWL needs updating.
- ldd r0, Y + G_EWLState + EWLS_UpdateCountdown
- cpse r0, r1
- rjmp 4f
- ; This transmitter has sent enough messages that its
- ; Next Sequence Number should be saved to EEPROM (with
- ; wear levelling) in case power is lost.
- ldiw Z, AuthenticationData
- ldd r0, Z + AD_SequenceNumber + 0
- std Y + G_EWLState + EWLS_NewSequenceNumber + 0, r0
- ldd r0, Z + AD_SequenceNumber + 1
- std Y + G_EWLState + EWLS_NewSequenceNumber + 1, r0
- ldd r0, Z + AD_SequenceNumber + 2
- std Y + G_EWLState + EWLS_NewSequenceNumber + 2, r0
- ldd r0, Z + AD_SequenceNumber + 3
- std Y + G_EWLState + EWLS_NewSequenceNumber + 3, r0
- ldi r17, EWL_COUNTS_BETWEEN_WRITES
- std Y + G_EWLState + EWLS_UpdateCountdown, r17
- ldi r17, 5 ; 4 for the NSN and 1 for the status ring
- std Y + G_EWLState + EWLS_NumBytesToWrite, r17
- ; 33 cycles so far
- rjmp 4f
- 1: ; 6 cycles so far
- ; Either a byte of the new NSN or the EWL status value is to be written.
- ; Only proceed if the EEPROM is not busy.
- sbic _SFR_IO_ADDR(EECR), EEPE
- rjmp 4f
- ; Get the next EWL slot index and value ready.
- ldd r20, Y + G_EWLState + EWLS_SlotIndex
- ldd r21, Y + G_EWLState + EWLS_SlotValue
- dec r20
- cpi r20, EWL_INDEX_RANGE
- ifcc
- ldi r20, EWL_INDEX_RANGE - 1
- dec r21
- ; 17 cycles so far
- ; Update the byte counter early.
- dec r17
- std Y + G_EWLState + EWLS_NumBytesToWrite, r17
- breq 2f
- cpi r17, 5
- brcc 6f
- ; Write a byte of the new Next Sequence Number.
- dec r17
- ldiw Z, Globals + G_EWLState + EWLS_NewSequenceNumber
- add ZL, r17
- adc ZH, r1
- mov r0, r20
- lsl r0
- lsl r0
- add r0, r17
- ldiw X, EEPROM_EWLDataRing
- add XL, r0
- adc XH, r1
- ld r0, Z
- ; 38 cycles so far
- rjmp 3f
- 2: ; 22 cycles so far
- ; Update the EWL slot data in SRAM.
- std Y + G_EWLState + EWLS_SlotIndex, r20
- std Y + G_EWLState + EWLS_SlotValue, r21
- ; Write to the EWL status ring.
- ldiw X, EEPROM_EWLStatusRing
- add XL, r20
- adc XH, r1
- mov r0, r21
- ; 31 cycles so far
- 3: ; 40 or 31 cycles so far
- rjmp WriteEEPROMByte ; 23 - 8 + 2 cycles
- 4: ret
- 6: ; Too many bytes to write. Ignore.
- std Y + G_EWLState + EWLS_NumBytesToWrite, r1
- ret
- ; Max 65 cycles, including call
- ;-------------------------------------------------------------------------------
- FullyUpdateEWLData:
- ; Update the EWL data so that the sequence number is fully committed to EEPROM,
- ; however long it takes.
- std Y + G_EWLState + EWLS_UpdateCountdown, r1
- 1: rcall LazilyUpdateEWLData
- ldd r0, Y + G_EWLState + EWLS_UpdateCountdown
- tst r0
- breq 1b
- ret
- ;-------------------------------------------------------------------------------
- MutateRandomData:
- ; In: r6:r4 = 32kHz counter
- ; Out: r0 = byte written to the random data pool
- movw r14, YL
- ldiw Y, EntropyHarvester
- ; Select the next byte of the random data to mutate.
- ldd r16, Y + EH_MutationIndex
- subi r16, -EH_MUTATION_INDEX_ADVANCE
- andi r16, EH_MUTATION_INDEX_MASK
- std Y + EH_MutationIndex, r16
- ldiw Z, EntropyHarvester + EH_RandomData
- add ZL, r16
- adc ZH, r1
- ; Mutate with the help of the 32kHz counter
- ld r0, Z
- add r0, r5 ; Timer bits 8 to 10 are adequate.
- ror r0
- adc r0, r4 ; Timer bits 3 to 7 are useful.
- st Z, r0
- movw YL, r14
- ; 21 cycles so far
- ret
- ; 29 cycles including call
- ;-------------------------------------------------------------------------------
- RandomiseCMACKey:
- ; Abuse the key part of the random data a little, in case
- ; an insufficient amount of entropy was harvested between
- ; transmissions of the secret key.
- ldiw Z, EntropyHarvester + EH_RandomData + 0
- ldd r8, Z + 0
- ldd r9, Z + 1
- ldd r10, Z + 2
- ldd r11, Z + 3
- ldiw X, EntropyHarvester + EH_RandomData + 16
- movw ZL, XL
- ldd r0, Z + 0
- add r0, r8
- std Z + 0, r0
- ldd r8, Z + 7
- add r8, r5
- ldd r0, Z + 2
- sbc r0, r9
- dec r0
- std Z + 7, r0
- ldd r0, Z + 12
- sbc r0, r10
- std Z + 2, r0
- ror r8
- adc r8, r11
- std Z + 12, r8
- rcall AES_AdvanceCMACSubKey
- ; Mutilate the existing CMAC key
- ldiw Z, EntropyHarvester + EH_RandomData + 0
- ldiw X, AuthenticationData + AD_CMACKey
- rcall Xor16B
- ; Random data and a random key should be effective in
- ; producing a nice new key.
- ldiw Z, EntropyHarvester + EH_RandomData + 16
- ldiw X, AuthenticationData + AD_CMACKey
- ldiw r25:r24, AES_Matrix_W
- rcall AES_Encrypt
- ; Now for the subkey K2
- ldiw Z, AuthenticationData + AD_CMACKey
- ldiw X, AuthenticationData + AD_CMACSubkeyK2 + 16
- ldiw r25:r24, AES_Matrix_W
- ldi r16, 16
- 1: st -X, r1
- dec r16
- brne 1b
- rcall AES_Encrypt
- ldiw X, AuthenticationData + AD_CMACSubkeyK2
- movw ZL, XL
- rcall AES_AdvanceCMACSubKey
- ldiw X, AuthenticationData + AD_CMACSubkeyK2
- movw ZL, XL
- rjmp AES_AdvanceCMACSubKey
- ;-------------------------------------------------------------------------------
- BuildTeachMessage:
- ; In: r24 = 0 if the shared key is be used to encrypt the secret key (normal) or
- ; 1 if the secret key is to be unprotected (timed delay mode).
- ; The message is in big-endian format.
- ; Copy the serial number and sequence number together.
- ldiw X, AuthenticationData + AD_SerialNumber
- ldiw Z, Globals + G_Transmitter + Tx_Data + TeachMsg_SerialNumber
- 1: ld r8, X+
- ld r9, X+
- ld r10, X+
- ld r11, X+
- st Z+, r11
- st Z+, r10
- st Z+, r9
- st Z+, r8
- com r1
- brne 1b
- ldiw Z, Globals + G_Transmitter + Tx_Data + TeachMsg_AuxData
- std Z + 0, r1
- std Z + 1, r1
- sbrc r24, 0
- std Z + 1, r2 ; Mark the teach message as unencrypted.
- ldiw Z, AuthenticationData + AD_CMACKey
- ldiw X, Globals + G_Transmitter + Tx_Data + TeachMsg_EncryptedCMACKey
- rcall Copy16B
- ldiw X, EEPROM_SharedKey
- ldiw Z, AES_Matrix_W
- ldi r16, 16
- rcall ReadEEPROMBlock
- ldiw Z, AES_Matrix_W
- ldiw X, Globals + G_Transmitter + Tx_Data + TeachMsg_EncryptedCMACKey
- sbrs r24, 0
- rcall Xor16B
- ldiw X, Globals + G_Transmitter + Tx_Data
- ldi r16, TeachMsgSize - 2
- clr r17
- rcall CalculateCRC_CCITT
- ; Store the CRC in big-endian format, not just because other elements
- ; in the message big-endian, but because the CCITT CRC of a message
- ; appended with its own CRC stored high-byte-first is zero.
- st X+, r17
- st X+, r16
- ret
- ;-------------------------------------------------------------------------------
- ; Initialisation
- ;-------------------------------------------------------------------------------
- InitialiseRegisterConstants:
- ; Out: r1 = 0
- ; r2 = 1
- ; r3 = 255
- ; Y = Globals
- ; r1 = 0
- clr r1
- ; r2 = 1, handy for carry-changing inc/dec via add/sub.
- clr r2
- inc r2
- ; r3 = 255 for sign extension.
- clr r3
- dec r3
- ldiw Y, Globals
- ret
- ;-------------------------------------------------------------------------------
- InitialiseHardware:
- ; No interrupts!
- cli
- ; Clear the watchdog reset flag so that it doesn't disable the
- ; the watchdog timer.
- in r16, _SFR_IO_ADDR(MCUSR)
- andi r16, ~(1 << WDRF)
- out _SFR_IO_ADDR(MCUSR), r16
- ; Start the watchdog timer and have it force a reset of the CPU if
- ; the timer isn't reset at least once every 0.5 seconds.
- ldi r16, (1 << WDCE) | (1 << WDE)
- out _SFR_IO_ADDR(WDTCR), r16
- ldi r16, (0 << WDCE) | (1 << WDE) | (0 << WDP3) | (0b101 << WDP0)
- out _SFR_IO_ADDR(WDTCR), r16
- ; Halt and configure Timer/Counter 0 to run at 8MHz.
- ldi r18, (1 << TSM) | (1 << PSR0)
- out _SFR_IO_ADDR(GTCCR), r18
- ldi r18, (0 << WGM02) | (0b001 << CS00)
- out _SFR_IO_ADDR(TCCR0B), r18
- out _SFR_IO_ADDR(TCNT0), r1
- ; Start the counting.
- out _SFR_IO_ADDR(GTCCR), r1
- ; Set Data Direction and pull-ups
- ldi r18, (1 << INPUT_BIT_PRIMARY_SENSOR) |\
- (1 << INPUT_BIT_SECONDARY_SENSOR) |\
- (0 << INPUT_BIT_BUTTONS)
- ldi r19, (1 << OUTPUT_BIT_ACTIVITY_LED) |\
- (1 << OUTPUT_BIT_RADIO)
- out _SFR_IO_ADDR(PORTB), r18
- out _SFR_IO_ADDR(DDRB), r19
- ; 03 ADCSRB [ BIN ACME IPR --- --- ADTS2 ADTS1 ADTS0 ]
- ; 04 ADCL [ ADC Data Register Low Byte ]
- ; 05 ADCH [ ADC Data Register High Byte ]
- ; 06 ADCSRA [ ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0 ]
- ; 07 ADMUX [ REFS1 REFS0 ADLAR REFS2 MUX3 MUX2 MUX1 MUX0 ]
- ; 08 ACSR [ ACD ACBG ACO ACI ACIE --- ACIS1 ACIS0 ]
- ; 14 DIDR0 [ --- --- ADC0D ADC2D ADC3D ADC1D AIN1D AIN0D ]
- ; Disable the digital input buffer for the pin on which
- ; we are to receive analogue input.
- ldi r18, 1 << BUTTONS_DIGITAL_INPUT_DISABLE_BIT
- out _SFR_IO_ADDR(DIDR0), r18
- ldi r18, 0x00
- out _SFR_IO_ADDR(ADCSRB), r18
- ldi r18, (1 << ADLAR) | (BUTTONS_ADC_MUX_SELECTOR << MUX0)
- out _SFR_IO_ADDR(ADMUX), r18
- ; Single-shot mode
- ; Start the conversion early to avoid spurious button readings.
- ldi r18, (1 << ADEN) | (1 << ADSC) | (0 << ADATE) | (0 << ADIF) |\
- (0b110 << ADPS0) ; CK/64 => 125kHz ADC clock
- out _SFR_IO_ADDR(ADCSRA), r18
- ret
- ;-------------------------------------------------------------------------------
- ClearGlobals:
- movw ZL, YL
- ldi r18, (VariablesEnd - Globals) / 2
- 1: st Z+, r1
- st Z+, r1
- dec r18
- brne 1b
- ret
- ;-------------------------------------------------------------------------------
- LoadEverythingFromEEPROM:
- ; Load the sound indices, stored complemented in EEPROM.
- ; Bits 0 to 3 is the sound index for the primary sensor.
- ; Bits 4 to 7 is the sound index for the secondary sensor.
- ldiw X, EEPROM_InvSoundIndices
- rcall ReadEEPROMByte
- com r0
- std Y + G_SoundIndices, r0
- ; Load the activation senses
- ; Bits 0 and 1 are for the primary and secondary sensors respectively.
- ; A sensor activation bit value of 0 means that the input at the
- ; sensor's pin on the MCU is active high and a value of 1 means
- ; that the pin is active low.
- ldiw X, EEPROM_SensorActivationSenses
- rcall ReadEEPROMByte
- ldi r16, 0x03
- and r16, r0
- std Y + G_SensorActivationSenses, r16
- sts TASSState + TASS_NewSensorActivationSenses, r16
- ; Load the authentication data which allows this transmitter to
- ; be associated with one or more receivers.
- ldiw Z, AuthenticationData + AD_SerialNumber
- ldiw X, EEPROM_SerialNumber
- ldi r16, 4
- rcall ReadEEPROMBlock
- ldiw Z, AuthenticationData + AD_CMACKey
- ldiw X, EEPROM_CMACKey
- ldi r16, 16
- rcall ReadEEPROMBlock
- ldiw Z, AuthenticationData
- std Z + AD_HaveK2, r1
- ; Load the EEPROM Wear Levelling state and the sequence number
- ; necessary for the authentication system to maintain synchronisation.
- ldiw X, EEPROM_EWLStatusRing
- ldiw Z, EEPROM_EWLDataRing
- rcall FindCurrentEWLDataSlot
- std Y + G_EWLState + EWLS_SlotIndex, r16
- std Y + G_EWLState + EWLS_SlotValue, r17
- movw XL, ZL
- ldiw Z, AuthenticationData + AD_SequenceNumber
- ldi r16, 4
- rcall ReadEEPROMBlock
- ; Advance the sequence number in case the power was lost before
- ; the EWL data could be updated.
- ldiw Z, AuthenticationData
- ldd r16, Z + AD_SequenceNumber + 0
- ldd r17, Z + AD_SequenceNumber + 1
- ldd r18, Z + AD_SequenceNumber + 2
- ldd r19, Z + AD_SequenceNumber + 3
- ldi r20, EWL_COUNTS_BETWEEN_WRITES + 2 ; (+2 for good measure)
- add r16, r20
- adc r17, r1
- adc r18, r1
- adc r19, r1
- std Z + AD_SequenceNumber + 0, r16
- std Z + AD_SequenceNumber + 1, r17
- std Z + AD_SequenceNumber + 2, r18
- std Z + AD_SequenceNumber + 3, r19
- ldi r16, 1
- std Y + G_EWLState + EWLS_UpdateCountdown, r16
- ; Load the random data harvested so far.
- ldiw Z, EntropyHarvester + EH_RandomData
- ldiw X, EEPROM_RandomData
- ldi r16, EH_MUTATION_INDEX_RANGE
- rcall ReadEEPROMBlock
- ; Add a bit of extra wear levelling of the random data.
- ldiw Z, EntropyHarvester
- ldd r16, Z + EH_RandomData + EH_AUX_RANDOM_DATA_START_INDEX
- andi r16, EH_MUTATION_INDEX_MASK
- std Z + EH_EEPROMUpdateIndex, r16
- ret
- ;-------------------------------------------------------------------------------
- ; main
- ;-------------------------------------------------------------------------------
- main:
- rcall InitialiseRegisterConstants
- rcall InitialiseHardware
- rcall ClearGlobals
- wdr
- rcall LoadEverythingFromEEPROM
- ldi r18, 127
- std Y + G_PrimarySensorIntegral, r18
- std Y + G_SecondarySensorIntegral, r18
- ; Initialise the AES-CMAC authenticator state.
- ldi r18, AUTH_STATE_IDLE
- std Y + G_AuthenticationState, r18
- ldi r18, AES_STATE_IDLE
- std Y + G_AESState, r18
- ; Reset the 32kHz counter
- clr r4
- clr r5
- clr r6
- main_Loop:
- ; Time share
- ;
- ; 32kHz:
- ; Reset watchdog (1)
- ; Synchronise (35)
- ; Update 32kHz counter (3)
- ; Update transmit pin (28)
- ; Time share 32kHz by 8 into 4kHz tasks (11)
- ; 0: Transmit packet (138)
- ; 1: Authentication (146)
- ; 2: Teach And Sound Select tasks
- ; Time share 4kHz by 4 into 1kHz tasks (Max 7)
- ; 0: ADC button input and TASS timers (121)
- ; 1: Button logic (118)
- ; 2: Transmission tasks scheduling (122+)
- ; 3:
- ; 3: Sensor input conditioning and entropy harvesting (148)
- ; 4: Sensor state transmission bursts and EWL updating (153)
- ; 5: Refresh EEPROM (67)
- ; 6:
- ; 7:
- wdr
- main_Synchronise:
- ; 32kHz implies a period of 31.25us, 250 counts of a 8MHz counter.
- ; The timer match value should be therefore be 250 counts ahead
- ; of the previous value.
- ldd r24, Y + G_CurrentTimer0Match
- subi r24, -250 ; "addi r24, 244" but with an opcode which exists
- std Y + G_CurrentTimer0Match, r24
- in r0, _SFR_IO_ADDR(TCNT0)
- sub r24, r0
- rcall DelayNCycles
- ; 7 + 28 = 35 cycles
- ;; We have too much spare time!
- ;ldi r24, 200
- ;rcall DelayNCycles
- main_Update32kHzCounter:
- ; r6:r4 = 32kHz counter value
- ; f = 16000 * 2^-b Hz
- ; T = 2^b / 16000 s
- ; b = log2(16000 / f)
- ; b = log2(16000 * T))
- ; Bit Edge f Edge T
- ; 0 32kHz 31.25us
- ; 1 16kHz 62.5us
- ; 2 8kHz 125us
- ; 3 4kHz 250us
- ; 4 2kHz 500us
- ; 5 1kHz 1ms
- ; 6 500Hz 2ms
- ; 7 250Hz 4ms
- ; 8 125Hz 8ms
- ; 9 62.5Hz 16ms
- ; 10 31.25Hz 32ms
- ; 11 15.625Hz 64ms
- ; 12 7.8125Hz 128ms
- ; 13 3.9106Hz 256ms
- ; 14 1.9531Hz 512ms
- ; 15 0.9766Hz 1024ms
- ; 16 2.05s
- ; 17 4.10s
- ; 18 8.19s
- ; 19 16.38s
- ; 20 32.77s
- ; 21 65.54s
- ; 22 131.07s
- ; 23 262.14s
- ; Clocked 524.29s
- add r4, r2
- adc r5, r1
- adc r6, r1
- ; 3 cycles
- main_UpdateTransmitPin:
- ; See if there's anything in the buffer.
- ldd r18, Y + G_Transmitter + Tx_TxBit + TxBit_HeadIx
- ldd r19, Y + G_Transmitter + Tx_TxBit + TxBit_TailIx
- cp r18, r19
- brne 1f
- rcall Delay10Cycles
- rcall Delay10Cycles
- rjmp 3f
- 1: ; The output ring buffer is arranged such that even offsets represent
- ; marks and odd offsets represent spaces.
- ; Update the transmission data pin while the timing is exact.
- in r20, _SFR_IO_ADDR(PORTB)
- mov r0, r18
- com r0
- bst r0, 0
- bld r20, OUTPUT_BIT_RADIO
- out _SFR_IO_ADDR(PORTB), r20
- ; The buffer still has something in it.
- ldiw X, TxRunLengthsRingBuffer
- add XL, r18
- adc XH, r1
- ld r0, X
- dec r0
- st X, r0
- breq 2f
- nop
- adiw XL, 0
- rjmp 3f
- 2: ; Advance to the next mark or space.
- inc r18
- andi r18, TX_RING_BUFFER_INDEX_MASK
- std Y + G_Transmitter + Tx_TxBit + TxBit_HeadIx, r18
- 3:
- ; 28 cycles
- main_TimeShare32By8:
- sbrc r4, 2
- rjmp 4f
- nop
- sbrc r4, 1
- rjmp 2f
- nop
- sbrc r4, 0
- rjmp 1f
- nop
- rjmp main_T0_TransmitPacket
- 1: rjmp main_T1_Authentication
- 2: sbrc r4, 0
- rjmp 3f
- nop
- rjmp main_T2_TeachAndSoundSelectTasks
- 3: rjmp main_T3_SensorInputConditioningAndEntropyHarvesting
- 4: sbrc r4, 1
- rjmp 6f
- nop
- sbrc r4, 0
- rjmp 5f
- nop
- rjmp main_T4_SensorStateTxBurstsAndEWLUpdates
- 5: rjmp main_T5_RefreshEEPROM
- 6: sbrc r4, 0
- rjmp 7f
- nop
- rjmp main_T6
- 7: rjmp main_T7
- ; 11 cycles
- main_T0_TransmitPacket:
- ; Find how many mark-space pairs are free.
- ldd r18, Y + G_Transmitter + Tx_TxBit + TxBit_HeadIx
- ldd r19, Y + G_Transmitter + Tx_TxBit + TxBit_TailIx
- sub r18, r19
- dec r18
- andi r18, TX_RING_BUFFER_INDEX_MASK
- lsr r18
- ; Jump to the handler for the current state.
- ldd r20, Y + G_Transmitter + Tx_State
- cpi r20, TX_STATE_DATA
- breq main_TxState_Data ; 13 cycles
- brcc 1f
- cpi r20, TX_STATE_BEGIN
- breq main_TxState_Begin ; 16 cycles
- brcc main_TxState_Sync ; 17 cycles
- rjmp main_TxState_Idle ; 18 cycles
- 1: cpi r20, TX_STATE_TERMINATOR
- ifne
- rjmp main_TxState_Rest ; 21 cycles
- rjmp main_TxState_Terminator ; 22 cycles
- main_TxState_Idle:
- ; 18 cycles so far
- rjmp main_Loop
- ; 20 cycles
- main_TxState_Begin:
- ; 16 cycles so far
- ldd r0, Y + G_Transmitter + Tx_Data + 0
- std Y + G_Transmitter + Tx_ShiftRegister, r0
- std Y + G_Transmitter + Tx_Parity, r1
- std Y + G_Transmitter + Tx_NumBytesSent, r1
- ldi r20, TX_STATE_SYNC
- std Y + G_Transmitter + Tx_State, r20
- ldi r20, TX_NUMBER_OF_LEADER_PULSES + 1
- std Y + G_Transmitter + Tx_Counter, r20
- ; Fall through to main_TxState_Sync.
- ; 30 cycles so far
- main_TxState_Sync:
- ; 17 or 30 cycles so far
- ; Limit the number of mark-space pairs to be buffered in one turn.
- ldi r23, 2
- cp r18, r23
- ifcc
- mov r18, r23
- ldd r22, Y + G_Transmitter + Tx_Counter
- cp r22, r18
- ifcs
- mov r18, r22
- tst r18
- breq 5f
- 1: ; The last two mark-space pairs are modified to include a long sync
- ; pulse which maintains a minimal DC bias.
- ; The synchronisation pattern is 101010...1010101000111001.
- cpi r22, 2
- breq 2f
- brcc 3f
- ; End of synchronisation: Long mark followed by a space that is
- ; twice the length of a short space.
- ldi r20, 3 * TX_TIME_UNIT
- ldi r21, 2 * TX_TIME_UNIT
- rjmp 4f
- 2: ; The last leader pulse has a long space to maintain DC balance.
- ldi r20, TX_TIME_UNIT
- ldi r21, 3 * TX_TIME_UNIT
- rjmp 4f
- 3: ; The leader pattern makes the radio receiver AGC happy.
- ldi r20, TX_TIME_UNIT
- ldi r21, TX_TIME_UNIT
- nop
- 4: dec r22
- rcall main_Tx_BufferMarkSpace
- dec r18
- brne 1b
- std Y + G_Transmitter + Tx_Counter, r22
- 5: ; (17 or 26) + (12 or 12+(41n)-1+2) cycles
- ; Are there any more synchronisation pulses to buffer?
- cpse r22, r1
- rjmp main_Loop ; 33..124 cycles
- ; Begin data transmission.
- ldi r20, TX_STATE_DATA
- std Y + G_Transmitter + Tx_State, r20
- ldi r20, 8
- std Y + G_Transmitter + Tx_Counter, r20
- ; Start the current run length of the second half of the bit 1 which
- ; follows the long space-mark which terminates the leader.
- ldiw X, TxRunLengthsRingBuffer
- add XL, r19
- adc XH, r1
- ldi r20, TX_TIME_UNIT
- st X, r20
- rjmp main_Loop
- ; Max 142 cycles
- main_TxState_Data:
- ; 13 cycles so far
- ; Proceed only if there is room for two run entries (1 pair).
- tst r18
- ifeq
- rjmp main_Loop ; 17 cycles
- ldd r20, Y + G_Transmitter + Tx_NumBytesToSend
- tst r20
- breq main_TxState_Terminator ; 21 cycles
- ldd r21, Y + G_Transmitter + Tx_NumBytesSent
- ldd r22, Y + G_Transmitter + Tx_Counter
- tst r22
- breq main_TxState_Data_Parity ; 27 cycles
- ; Fall through to main_TxState_Data_Bit.
- main_TxState_Data_Bit:
- ; 26 cycles so far
- dec r22
- std Y + G_Transmitter + Tx_Counter, r22
- ; Fetch the current data byte.
- ldd r0, Y + G_Transmitter + Tx_ShiftRegister
- ; Rotate-left-circular the current data byte, storing a bit into T.
- bst r0, 7
- add r0, r0
- adc r0, r1
- std Y + G_Transmitter + Tx_ShiftRegister, r0
- ; Update the parity for this byte.
- ldd r0, Y + G_Transmitter + Tx_Parity
- ifts
- inc r0
- std Y + G_Transmitter + Tx_Parity, r0
- rjmp main_TxState_Data_ModulateBit ; 44 cycles
- main_TxState_Data_Parity:
- ; 27 cycles so far
- dec r20
- std Y + G_Transmitter + Tx_NumBytesToSend, r20
- inc r21
- std Y + G_Transmitter + Tx_NumBytesSent, r21
- movw XL, YL
- adiw XL, G_Transmitter + Tx_Data
- add XL, r21
- adc XH, r1
- ld r0, X
- std Y + G_Transmitter + Tx_ShiftRegister, r0
- ldi r22, 8
- std Y + G_Transmitter + Tx_Counter, r22
- ldd r0, Y + G_Transmitter + Tx_Parity
- std Y + G_Transmitter + Tx_Parity, r1
- ; Even parity is used.
- bst r0, 0
- ; 50 cycles so far
- ; Fall through to main_TxState_Data_ModulateBit.
- main_TxState_Data_ModulateBit:
- ; 44 or 51 cycles so far
- ; From the T flag, prepare the Manchester-encoded bits
- ; in the first two bits of r18. Bit 0 first, Bit 1 second.
- ;
- ; Data bit First Second
- ; 0 0 1
- ; 1 1 0
- mov r18, r1
- bld r18, 0
- inc r18
- bld r18, 1
- ; Submit the Manchester bits to the run length ring buffer.
- ; Manchester bit duration in 32kHz ticks
- ldi r23, TX_TIME_UNIT
- ; The run length counter is just past the end of the ring buffer.
- ldiw X, TxRunLengthsRingBuffer
- add XL, r19
- adc XH, r1
- clr r20
- ; 54 or 61 cycles so far
- 1: ; See if the run state is to change.
- mov r0, r18
- eor r0, r19
- lsr r0
- brcc 2f
- ; Increase run length.
- ld r0, X
- add r0, r23
- st X, r0
- adiw XL, 0
- rjmp 3f
- 2: ; Queue the current run length.
- inc r19
- andi r19, TX_RING_BUFFER_INDEX_MASK
- ; Start a new run.
- ldiw X, TxRunLengthsRingBuffer
- add XL, r19
- adc XH, r1
- st X, r23
- ; Next Manchester bit.
- 3: lsr r18
- ; 14 cycles in loop so far
- com r20
- brne 1b
- std Y + G_Transmitter + Tx_TxBit + TxBit_TailIx, r19
- rjmp main_Loop
- ; 89 or 96 cycles
- main_TxState_Terminator:
- ; 22 cycles so far
- ; There is no real terminator to transmit in this encoding scheme.
- ; However, the current run length needs to be enqueued if it's for
- ; a high state. Then a long space is to be enqueued.
- ldiw X, TxRunLengthsRingBuffer
- add XL, r19
- adc XH, r1
- sbrc r19, 0
- rjmp 1f
- inc r19
- andi r19, TX_RING_BUFFER_INDEX_MASK
- ldiw X, TxRunLengthsRingBuffer
- add XL, r19
- adc XH, r1
- 1: ldi r20, TX_RLB_REST_TIME
- st X, r20
- inc r19
- andi r19, TX_RING_BUFFER_INDEX_MASK
- std Y + G_Transmitter + Tx_TxBit + TxBit_TailIx, r19
- ldi r20, TX_STATE_REST
- std Y + G_Transmitter + Tx_State, r20
- ldi r20, TX_TASK_REST_TIME
- std Y + G_Transmitter + Tx_Counter, r20
- rjmp main_Loop
- ; 44 or 49 cycles
- main_TxState_Rest:
- ; 21 cycles so far
- ldd r20, Y + G_Transmitter + Tx_Counter
- tst r20
- breq 1f
- dec r20
- std Y + G_Transmitter + Tx_Counter, r20
- rjmp main_Loop ; 30 cycles
- 1: ldd r18, Y + G_Transmitter + Tx_TxBit + TxBit_HeadIx
- ldd r19, Y + G_Transmitter + Tx_TxBit + TxBit_TailIx
- cp r18, r19
- brne 2f
- ldi r20, TX_STATE_IDLE
- std Y + G_Transmitter + Tx_State, r20
- 2:
- rjmp main_Loop
- ; 35 or 37 cycles
- main_Tx_BufferMarkSpace:
- ; r19: Transmit run length ring buffer tail index
- ; r20: Mark length in 32kHz ticks
- ; r21: Space length in 32kHz ticks
- ; Y: Global variables
- clr r0
- 1: ldiw X, TxRunLengthsRingBuffer
- add XL, r19
- adc XH, r1
- st X, r20
- inc r19
- andi r19, TX_RING_BUFFER_INDEX_MASK
- mov r20, r21
- com r0
- brne 1b
- std Y + G_Transmitter + Tx_TxBit + TxBit_TailIx, r19
- ret
- ; 30 cycles including call
- main_T1_Authentication:
- ldd r20, Y + G_AESState
- cpi r20, AES_STATE_BEGIN
- brcc main_AES_IdleOrStartAES
- sub r20, r2
- brcs main_Trampoline_AES_Finished
- ifhs
- andi r20, 0xF6
- std Y + G_AESState, r20
- mov r21, r20
- andi r21, 0x0F
- breq main_AES_AddRoundKey
- dec r21
- breq main_AES_AdvanceRoundKey
- cpi r21, 0x05
- brcc main_AES_SubAndShift
- dec r21
- ; Fall though to main_AES_Mixcolumn.
- main_AES_Mixcolumn:
- ; 18 cycles so far
- ; Mix a single column.
- cpi r20, 0x05
- brne 1f
- ; Skip MixColumns in the final round.
- std Y + G_AESState, r2
- ldi r24, 0x36
- rjmp main_AES_AdvanceRoundKey_RudeEntryForRound10
- 1: lsl r21
- lsl r21
- ldiw X, AES_Matrix_M
- add XL, r21
- adc XH, r1
- ; 27 cycles so far
- rcall AES_MixColumn ; 68 + 8 cycles
- rjmp main_Loop
- ; 105 cycles
- main_AES_SubAndShift:
- ; 18 cycles so far
- ; Substitute bytes and shift rows.
- ldiw Y, AES_Matrix_M
- ; 20 cycles so far
- rcall AES_SubstituteAndShift ; 113 + 8 cycles
- ldiw Y, Globals
- rjmp main_Loop
- ; 145 cycles
- main_AES_AddRoundKey:
- ; 14 cycles so far
- ; Add the round key.
- ldiw Z, AES_Matrix_W
- ldiw X, AES_Matrix_M
- ; 18 cycles so far
- rcall Xor16B ; 112 + 8 cycles
- rjmp main_Loop
- ; 140 cycles
- main_AES_AdvanceRoundKey:
- ; 16 cycles so far
- ; Advance the round key.
- ldi r18, 0x1B
- ldd r24, Y + G_AESRoundConstantByte
- lsl r24
- ifcs
- eor r24, r18
- std Y + G_AESRoundConstantByte, r24
- main_AES_AdvanceRoundKey_RudeEntryForRound10:
- ; 24 or 25 cycles so far
- ldiw Y, AES_Matrix_W
- rcall AES_AdvanceRoundKey ; 107 + 8 cycles
- ldiw Y, Globals
- rjmp main_Loop
- ; 145 or 146 cycles
- main_AES_StartEncryption:
- ; 7 or 54 cycles so far
- ldi r20, 0x8D
- std Y + G_AESRoundConstantByte, r20
- ldi r20, 0xA1
- std Y + G_AESState, r20
- ldiw Z, AES_Matrix_K
- ldiw X, AES_Matrix_W
- rjmp main_Copy16BAndLoop ; +73 cycles
- ; 90 or 137 cycles
- main_Trampoline_AES_Finished:
- ; 7 cycles so far
- rjmp main_AES_Finished
- main_AES_IdleOrStartAES:
- ; 5 cycles so far
- breq main_AES_StartEncryption
- ; Fall though to main_Auth_AES_Idle.
- main_AES_Idle:
- ; 6 cycles so far
- ldd r20, Y + G_AuthenticationState
- cpi r20, AUTH_STATE_CMDMSG_XOR_K2
- breq main_Auth_CmdMsg_XorK2 ; 11 cycles
- cpi r20, AUTH_STATE_CMDMSG_LOAD_K
- breq main_Auth_CmdMsg_LoadK ; 13 cycles
- cpi r20, AUTH_STATE_K2_CLEAR
- breq main_Auth_K2_Clear ; 15 cycles
- cpi r20, AUTH_STATE_CMDMSG_BEGIN
- breq main_Trampoline_Auth_CmdMsg_Begin ; 17 cycles
- cpi r20, AUTH_STATE_K2_BEGIN
- breq main_Auth_K2_Begin ; 19 cycles
- ; 18 cycles so far
- ; Fall though to main_Auth_Idle.
- main_Auth_Idle:
- ; 18 cycles so far
- ldiw Z, AuthenticationData
- ldd r0, Z + AD_HaveK2
- tst r0
- breq main_Auth_K2_Begin ; 25 cycles
- rjmp main_Loop ; 26 cycles
- main_Auth_CmdMsg_XorK2:
- ; 11 cycles so far
- ldiw Z, AuthenticationData + AD_CMACSubkeyK2
- ldiw X, AES_Matrix_M
- rcall Xor16B ; 112 + 8 cycles
- ldi r20, AUTH_STATE_CMDMSG_CMAC
- std Y + G_AuthenticationState, r20
- ldi r20, AES_STATE_BEGIN
- std Y + G_AESState, r20
- rjmp main_Loop
- ; 143 cycles
- main_Auth_CmdMsg_LoadK:
- ; 13 cycles so far
- ; For a final block that was short before padding, AES-CMAC
- ; requires xoring with the subkey K2.
- ldi r20, AUTH_STATE_CMDMSG_XOR_K2
- std Y + G_AuthenticationState, r20
- ; Right now though, load K with the (secret) CMAC key.
- ldiw Z, AuthenticationData + AD_CMACKey
- ldiw X, AES_Matrix_K
- rjmp main_Copy16BAndLoop ; 69 cycles
- ; 91 cycles
- main_Trampoline_Auth_CmdMsg_Begin:
- ; 17 cycles so far
- rjmp main_Auth_CmdMsg_Begin
- main_Auth_K2_Begin:
- ; 19 or 25 cycles so far
- ldi r20, AUTH_STATE_K2_CLEAR
- std Y + G_AuthenticationState, r20
- ldiw Z, AuthenticationData + AD_CMACKey
- ldiw X, AES_Matrix_K
- rjmp main_Copy16BAndLoop ; +73 cycles
- ; 82 or 88 cycles
- main_Auth_K2_Clear:
- ; 15 cycles so far
- ldiw X, AES_Matrix_M
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- ldi r20, AUTH_STATE_K2_GEN_K1
- std Y + G_AuthenticationState, r20
- ; 52 cycles so far
- rjmp main_AES_StartEncryption
- ; 139 cycles
- main_AES_Finished:
- ; 9 cycles so far
- ldd r20, Y + G_AuthenticationState
- cpi r20, AUTH_STATE_CMDMSG_CMAC
- ifeq
- rjmp main_Auth_CmdMsg_WriteCMAC ; 15 cycles
- cpi r20, AUTH_STATE_K2_GEN_K2
- breq main_Auth_K2_GenK2 ; 17 cycles
- cpi r20, AUTH_STATE_K2_GEN_K1
- brne main_Auth_End ; 19 cycles
- ; Fall through to main_Auth_K2_GenK1.
- main_Auth_K2_GenK1:
- ; 18 cycles so far
- ldiw X, AES_Matrix_M
- movw ZL, XL
- rcall AES_AdvanceCMACSubKey ; 96 + 8 cycles
- ldi r20, AUTH_STATE_K2_GEN_K2
- std Y + G_AuthenticationState, r20
- rjmp main_Loop
- ; 130 cycles
- main_Auth_K2_GenK2:
- ; 17 cycles so far
- ldiw X, AES_Matrix_M
- ldiw Z, AuthenticationData + AD_CMACSubkeyK2
- std Z + AD_HaveK2 - AD_CMACSubkeyK2, r2
- rcall AES_AdvanceCMACSubKey ; 96 + 8 cycles
- ; 127 cycles so far
- ; Fall though to main_Auth_End.
- main_Auth_End:
- ; 127 or 19 cycles so far
- ldi r20, AUTH_STATE_IDLE
- std Y + G_AuthenticationState, r20
- ldi r20, AES_STATE_IDLE
- std Y + G_AESState, r20
- rjmp main_Loop
- ; 135 or 27 cycles
- main_Auth_CmdMsg_Begin:
- ; 19 cycles so far
- ldiw Z, AuthenticationData
- ; Compose the message, leaving the CMAC to be computed and written
- ; while the transmission routine is still sending the payload.
- ldd r8, Z + AD_SerialNumber + 0
- ldd r9, Z + AD_SerialNumber + 1
- ldd r10, Z + AD_SerialNumber + 2
- ldd r11, Z + AD_SerialNumber + 3
- std Y + G_Transmitter + Tx_Data + CmdMsg_SerialNumber + 0, r11
- std Y + G_Transmitter + Tx_Data + CmdMsg_SerialNumber + 1, r10
- std Y + G_Transmitter + Tx_Data + CmdMsg_SerialNumber + 2, r9
- std Y + G_Transmitter + Tx_Data + CmdMsg_SerialNumber + 3, r8
- ldd r16, Z + AD_SequenceNumber + 0
- ldd r17, Z + AD_SequenceNumber + 1
- ldd r18, Z + AD_SequenceNumber + 2
- ldd r19, Z + AD_SequenceNumber + 3
- std Y + G_Transmitter + Tx_Data + CmdMsg_SequenceNumber + 0, r19
- std Y + G_Transmitter + Tx_Data + CmdMsg_SequenceNumber + 1, r18
- std Y + G_Transmitter + Tx_Data + CmdMsg_SequenceNumber + 2, r17
- std Y + G_Transmitter + Tx_Data + CmdMsg_SequenceNumber + 3, r16
- ldd r20, Y + G_Transmitter + Tx_Data + CmdMsg_Command
- ldd r21, Y + G_Transmitter + Tx_Data + CmdMsg_Parameter
- ; Leave CmdMsg_Command and CmdMsg_Parameter as they are.
- ; 47 cycles so far
- ; AES-CMAC requires a short message block to be padded to the
- ; full 16 bytes with a bit one followed by however many bit
- ; zeros will fit.
- ldiw X, AES_Matrix_M
- st X+, r11
- st X+, r10
- st X+, r9
- st X+, r8
- st X+, r19
- st X+, r18
- st X+, r17
- st X+, r16
- st X+, r20
- st X+, r21
- ldi r20, 0x80
- st X+, r20
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- st X+, r1
- ; 73 cycles so far
- ; Advance the sequence number to foil replay attacks.
- add r16, r2
- adc r17, r1
- adc r18, r1
- adc r19, r1
- std Z + AD_SequenceNumber + 0, r16
- std Z + AD_SequenceNumber + 1, r17
- std Z + AD_SequenceNumber + 2, r18
- std Z + AD_SequenceNumber + 3, r19
- ldd r16, Y + G_EWLState + EWLS_UpdateCountdown
- sub r16, r2
- adc r16, r1
- std Y + G_EWLState + EWLS_UpdateCountdown, r16
- ldi r20, 14
- std Y + G_Transmitter + Tx_NumBytesToSend, r20
- ldi r20, TX_STATE_BEGIN
- std Y + G_Transmitter + Tx_State, r20
- ldi r20, AUTH_STATE_CMDMSG_LOAD_K
- std Y + G_AuthenticationState, r20
- rjmp main_Loop
- ; 102 cycles
- main_Auth_CmdMsg_WriteCMAC:
- ; 15 cycles so far
- ldi r20, AUTH_STATE_IDLE
- std Y + G_AuthenticationState, r20
- ldi r20, AES_STATE_IDLE
- std Y + G_AESState, r20
- ldiw X, AES_Matrix_M
- ldiw Z, Globals + G_Transmitter + Tx_Data
- ld r0, X+
- std Z + CmdMsg_CMAC + 0, r0
- ld r0, X+
- std Z + CmdMsg_CMAC + 1, r0
- ld r0, X+
- std Z + CmdMsg_CMAC + 2, r0
- ld r0, X+
- std Z + CmdMsg_CMAC + 3, r0
- ; 41 cycles
- rjmp main_Auth_End
- ; 43 cycles
- main_Copy16BAndLoop:
- 1: ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- ld r0, Z+
- st X+, r0
- com r1
- brne 1b
- rjmp main_Loop
- ; Max 146 cycles
- main_T2:
- rjmp main_Loop
- main_T3:
- rjmp main_Loop
- main_T2_TeachAndSoundSelectTasks:
- sbrs r4, 4
- rjmp 1f
- sbrc r4, 3
- rjmp main_T2_TASSTasks_T0_ADCInputAndTASSTimers ; 5 cycles
- rjmp main_T2_TASSTasks_T1_ButtonLogic ; 6 cycles
- 1: sbrc r4, 3
- rjmp main_T2_TASSTasks_T2_SaveAndTransmit ; 6 cycles
- rjmp main_T2_TASSTasks_T3 ; 7 cycles
- ; Max 7 cycles
- main_T2_TASSTasks_T0_ADCInputAndTASSTimers:
- ; The three buttons wired to ADC1 on pin 7 are connected to resistors.
- ;
- ; Vcc -----*---------------------------
- ; |
- ; R4 [ ]
- ; |
- ; *---------*---------*------> ADC input
- ; | | |
- ; R3 [ ] R2 [ ] R1 [ ]
- ; | | | R1 = 6.8k ohms
- ; | o | o | o R2 = 1.8k ohms
- ; TEACH [| SS2 [| SS1 [| R3 = 220 ohms
- ; | o | o | o R4 = 3.0k ohms or 3.3k ohms
- ; | | |
- ; GND -----*---------*---------*------
- ;
- ; As power supply fluctuations and contact resistance can affect the
- ; ADC readings, it is best to require only single-button combinations
- ; be interpreted.
- ;
- ; TEACH SS2 SS1 ADC ADCH Range
- ; 0 0 0 100% 255 216..255
- ; 0 0 1 69% 177 137..215
- ; 0 1 0 37% 96 57..136
- ; 1 x x <7% <18 0..56
- in r17, _SFR_IO_ADDR(ADCH)
- sbi _SFR_IO_ADDR(ADCSRA), ADSC
- cpi r17, 137
- brcs 1f
- ldi r16, 0b000
- cpi r17, 216
- adc r16, r1
- rjmp 2f
- 1: ldi r16, 0b010
- cpi r17, 57
- ifcs
- ldi r16, 0b100
- 2: ; 9 cycles so far
- ldd r0, Y + G_ADCButtons + ADCB_ProvisionalState
- ldd r17, Y + G_ADCButtons + ADCB_AcceptanceCountdown
- std Y + G_ADCButtons + ADCB_ProvisionalState, r16
- cpse r0, r16
- ldi r17, BUTTON_DB_DELAY_ADC
- sub r17, r2
- adc r17, r1
- std Y + G_ADCButtons + ADCB_AcceptanceCountdown, r17
- ldd r17, Y + G_ADCButtons + ADCB_State
- brne . + 2
- mov r17, r16
- std Y + G_ADCButtons + ADCB_State, r17
- ldd r0, Y + G_ADCButtons + ADCB_MutexState
- tst r17
- breq 3f
- tst r0
- ifeq
- 3: mov r0, r17
- std Y + G_ADCButtons + ADCB_MutexState, r0
- ; Max 36 cycles so far
- ldiw Z, TASSState
- ldd r8, Y + G_SlowClocks
- mov r7, r8
- bst r5, 3 ; Counting at 15.625Hz
- bld r8, bCLOCK_TASS
- std Y + G_SlowClocks, r8
- eor r7, r8
- bst r7, bCLOCK_TASS
- clr r7
- bld r7, 0
- ldd r16, Z + TASS_LongPressCountdown
- sub r16, r7
- adc r16, r1
- ldd r10, Z + TASS_SS1LongPressCountdown
- sub r10, r7
- adc r10, r1
- ldd r11, Z + TASS_SS2LongPressCountdown
- sub r11, r7
- adc r11, r1
- ldd r24, Y + G_TaskFlags1
- ldd r25, Y + G_TaskFlags2
- ldd r22, Z + TASS_PrimarySoundTestCountdown
- tst r22
- breq 1f
- sub r22, r7
- ifeq
- ori r24, mTASK1_SEND_PRIMARY_SOUND_B
- 1: ldd r23, Z + TASS_SecondarySoundTestCountdown
- tst r23
- breq 2f
- sub r23, r7
- ifeq
- ori r24, mTASK1_SEND_SECONDARY_SOUND_B
- 2: ldd r18, Y + G_SensorActivationSenses
- ldd r19, Z + TASS_NewSensorActivationSenses
- ldd r20, Z + TASS_Sensor1InversionCountdown
- ldd r21, Z + TASS_Sensor2InversionCountdown
- tst r20
- breq 3f
- sub r20, r7
- brne 3f
- bst r19, 0
- bld r18, 0
- 3: tst r21
- breq 4f
- sub r21, r7
- brne 4f
- bst r19, 1
- bld r18, 1
- 4: ldd r9, Z + TASS_PingIntervalCountdown
- sub r9, r7
- adc r9, r1
- std Z + TASS_PingIntervalCountdown, r9
- std Y + G_SensorActivationSenses, r18
- std Z + TASS_Sensor1InversionCountdown, r20
- std Z + TASS_Sensor2InversionCountdown, r21
- std Z + TASS_LongPressCountdown, r16
- std Z + TASS_SS1LongPressCountdown, r10
- std Z + TASS_SS2LongPressCountdown, r11
- std Z + TASS_PrimarySoundTestCountdown, r22
- std Z + TASS_SecondarySoundTestCountdown, r23
- std Y + G_TaskFlags1, r24
- std Y + G_TaskFlags2, r25
- rjmp main_Loop
- ; Max 36 + 91 = 127 cycles
- main_T2_TASSTasks_T1_ButtonLogic:
- ; Handle the Teach and Sound Select logic, along with the
- ; special functions. Special functions include sensor activation
- ; sense inversion, the self-timer for a delayed and unencrypted
- ; teach message transmission and pinging mode.
- ldiw Z, TASSState
- ldd r0, Y + G_ADCButtons + ADCB_MutexState
- ldd r7, Z + TASS_LastButtonsState
- std Z + TASS_LastButtonsState, r0
- ldd r24, Y + G_TaskFlags1
- ldd r25, Y + G_TaskFlags2
- ldd r16, Z + TASS_LongPressCountdown
- ldd r10, Z + TASS_SS1LongPressCountdown
- ldd r11, Z + TASS_SS2LongPressCountdown
- ldd r22, Z + TASS_PrimarySoundTestCountdown
- ldd r23, Z + TASS_SecondarySoundTestCountdown
- ldd r17, Z + TASS_TeachOrPingState
- cpse r17, r1
- rjmp 9f
- ; No particular mode is active.
- sbrc r0, 2
- rjmp 11f ; The Teach button has just been pressed.
- ; The Teach button is not currently pressed.
- ; 28 cycles so far
- ldi r18, SOUND_SELECT_BUTTON_VERY_LONG_PRESS_TIME
- mov r9, r18
- ldi r18, SOUND_SELECT_BUTTON_VERY_LONG_PRESS_TIME - \
- SOUND_SELECT_BUTTON_LONG_PRESS_TIME
- mov r12, r18
- ldi r16, TEACH_BUTTON_LONG_PRESS_TIME
- cpse r0, r1
- rjmp 2f
- cpse r7, r1
- rjmp 2f
- ; No button is being pressed and a button release did not just occur.
- ; Flash the LED during a transmission.
- ldd r8, Y + G_Transmitter + Tx_NumBytesSent
- com r8
- ldd r18, Y + G_Transmitter + Tx_State
- cpi r18, TX_STATE_SYNC
- breq 1f
- cpi r18, TX_STATE_DATA
- breq 1f
- clr r8
- 1: bst r8, 0
- in r8, _SFR_IO_ADDR(PORTB)
- bld r8, OUTPUT_BIT_ACTIVITY_LED
- out _SFR_IO_ADDR(PORTB), r8
- mov r10, r9
- mov r11, r9
- rjmp 8f ; 55 cycles
- 2: ; At least one of the Sound Select buttons is currently pressed
- ; or has just been released.
- ; Max 38 cycles so far
- std Z + TASS_NumTeachMessagesToSend, r1
- std Z + TASS_SuppressKeyRandomisation, r1
- ; See if a sound select button has been pressed for a very long time.
- ; That is the silly walk to active pinging mode.
- tst r10
- ifeq
- rjmp 15f
- tst r11
- ifeq
- rjmp 15f
- ; Flash the activity LED if one or both sound select buttons
- ; is held down for long, else keep it lit.
- bst r5, 3
- cp r10, r12
- brcs 3f
- cp r11, r12
- brcs 3f
- set
- 3: in r8, _SFR_IO_ADDR(PORTB)
- bld r8, OUTPUT_BIT_ACTIVITY_LED
- out _SFR_IO_ADDR(PORTB), r8
- ; Prepare to advance a sound index or toggle a sensor sense.
- ; Max 57 cycles so far
- ldd r8, Z + TASS_NewSensorActivationSenses
- ldd r18, Y + G_SoundIndices
- com r7
- or r7, r0
- ; Max 63 cycles so far
- ; See if the primary sound select button has just been released.
- sbrc r7, 0
- rjmp 5f
- cp r10, r12
- brcc 4f
- ; Toggle the primary sensor sense.
- eor r8, r2
- ldi r19, SENSE_INVERSION_DELAY
- std Z + TASS_Sensor1InversionCountdown, r19
- sbrs r8, 0
- ori r25, mTASK2_SAVE_SENSOR_ACTIVATION_SENSES |\
- mTASK2_SEND_PRIMARY_SENSE_NORMAL
- sbrc r8, 0
- ori r25, mTASK2_SAVE_SENSOR_ACTIVATION_SENSES |\
- mTASK2_SEND_PRIMARY_SENSE_INVERTED
- rjmp 5f
- 4: ; Advance the primary sound index.
- add r18, r2
- ifhs
- subi r18, 16
- ori r24, mTASK1_SAVE_SOUND_INDICES | mTASK1_SEND_PRIMARY_SOUND_A
- ldi r22, ACTIVATION_SOUND_TO_DEACTIVATION_SOUND_DELAY
- 5: sbrs r0, 0
- mov r10, r9
- ; Max 79 cycles so far
- ; See if the secondary sound select button has just been released.
- sbrc r7, 1
- rjmp 7f
- cp r11, r12
- brcc 6f
- ; Toggle the secondary sensor sense.
- ldi r19, 2
- eor r8, r19
- ldi r19, SENSE_INVERSION_DELAY
- std Z + TASS_Sensor2InversionCountdown, r19
- sbrs r8, 1
- ori r25, mTASK2_SAVE_SENSOR_ACTIVATION_SENSES |\
- mTASK2_SEND_SECONDARY_SENSE_NORMAL
- sbrc r8, 1
- ori r25, mTASK2_SAVE_SENSOR_ACTIVATION_SENSES |\
- mTASK2_SEND_SECONDARY_SENSE_INVERTED
- rjmp 7f
- 6: ; Advance the secondary sound index.
- subi r18, -16
- ori r24, mTASK1_SAVE_SOUND_INDICES | mTASK1_SEND_SECONDARY_SOUND_A
- ldi r23, ACTIVATION_SOUND_TO_DEACTIVATION_SOUND_DELAY
- 7: sbrs r0, 1
- mov r11, r9
- std Y + G_SoundIndices, r18
- std Z + TASS_NewSensorActivationSenses, r8
- ; Max 100 cycles so far
- ; Fall through...
- 8: std Z + TASS_LongPressCountdown, r16
- std Z + TASS_SS1LongPressCountdown, r10
- std Z + TASS_SS2LongPressCountdown, r11
- std Z + TASS_TeachOrPingState, r17
- std Z + TASS_PrimarySoundTestCountdown, r22
- std Z + TASS_SecondarySoundTestCountdown, r23
- std Y + G_TaskFlags1, r24
- std Y + G_TaskFlags2, r25
- rjmp main_Loop ; Max 118 cycles
- 9: ; A special mode is active.
- ; 27 cycles so far
- mov r10, r3
- mov r11, r3
- cpi r17, TASS_STATE_TEACH_PRESSED
- breq 11f
- cpi r17, TASS_STATE_TEACH_LONG_PRESSED
- breq 12f
- cpi r17, TASS_STATE_DELAYED_TEACH
- breq 13f
- cpi r17, TASS_STATE_SILLY_WALK_FOR_PING
- breq 15f
- cpi r17, TASS_STATE_PINGING
- breq 16f
- ; Assume TASS_STATE_WAIT_FOR_RELEASE and fall through.
- 10: ; To lessen the chance of accidental input, wait for all buttons
- ; to be released.
- ; 39 cycles so far
- sbi _SFR_IO_ADDR(PORTB), OUTPUT_BIT_ACTIVITY_LED
- cpse r0, r1
- rjmp 8b
- cbi _SFR_IO_ADDR(PORTB), OUTPUT_BIT_ACTIVITY_LED
- ldi r17, TASS_STATE_IDLE
- ser r16
- mov r10, r16
- mov r11, r16
- rjmp 8b ; 49 cycles
- 11: ; The Teach button is pressed, but not for very long yet.
- ; 32 or 29 cycles so far
- ldi r17, TASS_STATE_TEACH_PRESSED
- std Z + TASS_NumTeachMessagesToSend, r1
- std Z + TASS_SuppressKeyEncryption, r1
- sbi _SFR_IO_ADDR(PORTB), OUTPUT_BIT_ACTIVITY_LED
- tst r16
- ifeq
- ldi r17, TASS_STATE_TEACH_LONG_PRESSED
- cpse r0, r1
- rjmp 8b ; Max 44 cycles
- rjmp 18f ; Max 45 cycles
- 12: ; The Teach button is being subject to a long press.
- ; 34 cycles so far
- bst r5, 3
- in r8, _SFR_IO_ADDR(PORTB)
- bld r8, OUTPUT_BIT_ACTIVITY_LED
- out _SFR_IO_ADDR(PORTB), r8
- cpse r0, r1
- rjmp 8b ; 41 cycles
- cbi _SFR_IO_ADDR(PORTB), OUTPUT_BIT_ACTIVITY_LED
- ldi r17, TASS_STATE_DELAYED_TEACH
- ldi r16, 176 ; About 11 seconds
- std Z + TASS_SuppressKeyEncryption, r2
- rjmp 8b ; 47 cycles
- 13: ; The self-timer for the delayed teach function is counting down.
- ; 36 cycles so far
- tst r0
- brne 17f
- tst r16
- breq 18f
- ; Flash the self-timer LED.
- mov r18, r16
- ldi r19, 0x0F
- cpi r18, 32
- brcc 14f
- ldi r19, 0x03
- sbrs r18, 4
- lsr r19
- 14: clt
- and r18, r19
- ifeq
- set
- in r8, _SFR_IO_ADDR(PORTB)
- bld r8, OUTPUT_BIT_ACTIVITY_LED
- out _SFR_IO_ADDR(PORTB), r8
- rjmp 8b ; Max 56 cycles
- 15: ; The silly walk to activate pinging mode is in progress.
- ; Max 49 cycles so far
- ldi r17, TASS_STATE_SILLY_WALK_FOR_PING
- bst r5, 2
- in r8, _SFR_IO_ADDR(PORTB)
- bld r8, OUTPUT_BIT_ACTIVITY_LED
- out _SFR_IO_ADDR(PORTB), r8
- cpse r0, r1
- rjmp 8b ; Max 57 cycles
- cbi _SFR_IO_ADDR(PORTB), OUTPUT_BIT_ACTIVITY_LED
- ldi r18, PING_START_DELAY
- std Z + TASS_PingIntervalCountdown, r18
- ldi r18, 150 ; 150 pings 4 seconds apart (10 minutes)
- std Z + TASS_NumPingsToSend, r18
- ldi r17, TASS_STATE_PINGING
- rjmp 8b ; Max 66 cycles
- 16: ; Pinging mode is active.
- ; 40 cycles so far
- tst r0
- brne 17f
- bst r5, 7
- in r8, _SFR_IO_ADDR(PORTB)
- bld r8, OUTPUT_BIT_ACTIVITY_LED
- out _SFR_IO_ADDR(PORTB), r8
- ldd r18, Z + TASS_NumPingsToSend
- tst r18
- breq 17f ; 51 cycles
- ldd r19, Z + TASS_PingIntervalCountdown
- cpse r19, r1
- rjmp 8b ; 55 cycles
- ldi r19, PING_INTERVAL_DOUBLED >> 1
- .if PING_INTERVAL_DOUBLED & 1
- sbrc r6, 1
- inc r19
- .endif
- std Z + TASS_PingIntervalCountdown, r19
- ori r25, mTASK2_SEND_PING
- dec r18
- std Z + TASS_NumPingsToSend, r18
- breq 17f ; 65 cycles
- rjmp 8b ; 66 cycles
- 17: ; 65 or 39 cycles so far
- ldi r17, TASS_STATE_WAIT_FOR_RELEASE
- rjmp 8b ; Max 68 cycles
- 18: ; Issue the teach message!
- ; 45 or 41 cycles so far
- cbi _SFR_IO_ADDR(PORTB), OUTPUT_BIT_ACTIVITY_LED
- ser r16
- ldi r17, TASS_STATE_IDLE
- clr r22
- clr r23
- ori r24, mTASK1_SEND_TEACH_MESSAGE
- andi r24, ~(mTASK1_SEND_PRIMARY_SOUND_A |\
- mTASK1_SEND_PRIMARY_SOUND_B |\
- mTASK1_SEND_SECONDARY_SOUND_A |\
- mTASK1_SEND_SECONDARY_SOUND_B)
- ldi r18, 5
- std Z + TASS_NumTeachMessagesToSend, r18
- ; Max 55 cycles so far
- rjmp 8b
- ; Max 118 cycles
- main_T2_TASSTasks_T2_SaveAndTransmit:
- ldd r24, Y + G_TaskFlags1
- ldd r25, Y + G_TaskFlags2
- sbic _SFR_IO_ADDR(EECR), EEPE
- rjmp 2f
- sbrs r24, bTASK1_SAVE_SOUND_INDICES
- rjmp 1f
- ldiw X, EEPROM_InvSoundIndices
- ldd r0, Y + G_SoundIndices
- com r0
- rcall WriteEEPROMByte ; 23 cycles
- andi r24, ~(mTASK1_SAVE_SOUND_INDICES)
- rjmp 2f ; 39 cycles
- 1: sbrs r25, bTASK2_SAVE_SENSOR_ACTIVATION_SENSES
- rjmp 2f
- ldiw X, EEPROM_SensorActivationSenses
- lds r0, TASSState + TASS_NewSensorActivationSenses
- andi r25, ~(mTASK2_SAVE_SENSOR_ACTIVATION_SENSES)
- rcall WriteEEPROMByte ; 23 cycles
- ; Max 39 cycles so far
- ; Fall through
- 2: ; Max 39 cycles so far
- ldd r16, Y + G_Transmitter + Tx_State
- cpi r16, TX_STATE_IDLE
- brne 8f
- ldd r16, Y + G_AuthenticationState
- cpi r16, AUTH_STATE_IDLE
- brne 8f
- ldd r16, Y + G_AESState
- cpi r16, AES_STATE_IDLE
- brne 8f
- ; Max 51 cycles so far
- ldd r17, Y + G_SoundIndices
- sbrc r24, bTASK1_SEND_PRIMARY_SOUND_A
- rjmp 3f
- sbrc r24, bTASK1_SEND_PRIMARY_SOUND_B
- rjmp 4f
- sbrc r24, bTASK1_SEND_SECONDARY_SOUND_A
- rjmp 5f
- sbrc r24, bTASK1_SEND_SECONDARY_SOUND_B
- rjmp 6f
- sbrc r24, bTASK1_SEND_TEACH_MESSAGE
- rjmp 14f
- sbrc r25, bTASK2_SEND_PRIMARY_SENSE_NORMAL
- rjmp 9f
- sbrc r25, bTASK2_SEND_PRIMARY_SENSE_INVERTED
- rjmp 10f
- sbrc r25, bTASK2_SEND_SECONDARY_SENSE_NORMAL
- rjmp 11f
- sbrc r25, bTASK2_SEND_SECONDARY_SENSE_INVERTED
- rjmp 12f
- sbrc r25, bTASK2_SEND_PING
- rjmp 13f
- rjmp 8f
- 3: ; Activation sound for primary sensor
- ; Max 56 cycles so far
- andi r24, ~(mTASK1_SEND_PRIMARY_SOUND_A)
- ldi r16, 0b0101
- rjmp 7f
- 4: ; Deactivation sound for primary sensor
- ; Max 58 cycles so far
- andi r24, ~(mTASK1_SEND_PRIMARY_SOUND_B)
- ldi r16, 0b0100
- rjmp 7f
- 5: ; Activation sound for secondary sensor
- ; Max 60 cycles so far
- andi r24, ~(mTASK1_SEND_SECONDARY_SOUND_A)
- ldi r16, 0b0111
- swap r17
- rjmp 7f
- 6: ; Deactivation sound for secondary sensor
- ; Max 62 cycles so far
- andi r24, ~(mTASK1_SEND_SECONDARY_SOUND_B)
- ldi r16, 0b0110
- swap r17
- ; Fall through to transmission initiation.
- 7: ; Max 65 cycles so far
- ; Max 79 cycles
- andi r17, 0x0F
- std Y + G_Transmitter + Tx_Data + CmdMsg_Command, r16
- std Y + G_Transmitter + Tx_Data + CmdMsg_Parameter, r17
- ldi r16, AUTH_STATE_CMDMSG_BEGIN
- std Y + G_AuthenticationState, r16
- rcall MutateRandomData ; 21 + 8 cycles
- ; Max 116 cycles so far
- ; Fall through to the final part of the routine.
- 8: ; Max 116 cycles so far
- std Y + G_TaskFlags1, r24
- std Y + G_TaskFlags2, r25
- rjmp main_Loop ; Max 122 cycles
- 9: ; Report that the primary sensor is to be active high.
- ; Max 66 cycles so far
- andi r25, ~(mTASK2_SEND_PRIMARY_SENSE_NORMAL)
- ldi r16, 0b1000
- ldi r17, 0
- rjmp 7b
- 10: ; Report that the primary sensor is to be active low.
- ; Max 68 cycles so far
- andi r25, ~(mTASK2_SEND_PRIMARY_SENSE_INVERTED)
- ldi r16, 0b1001
- ldi r17, 1
- rjmp 7b
- 11: ; Report that the secondary sensor is to be active high.
- ; Max 70 cycles so far
- andi r25, ~(mTASK2_SEND_SECONDARY_SENSE_NORMAL)
- ldi r16, 0b1010
- ldi r17, 0
- rjmp 7b
- 12: ; Report that the secondary sensor is to be active low.
- ; Max 72 cycles so far
- andi r25, ~(mTASK2_SEND_SECONDARY_SENSE_INVERTED)
- ldi r16, 0b1011
- ldi r17, 1
- rjmp 7b
- 13: ; Ping the chime(s) to assist with radio range assessment.
- ; Max 74 cycles so far
- andi r25, ~(mTASK2_SEND_PING)
- ldi r16, 0b1000
- ldi r17, 2
- rjmp 7b ; Max 79 cycles
- 14: ; Send the teach message, perhaps after generating a new secret key.
- ; Max 64 cycles so far
- std Y + G_TaskFlags2, r25
- push r24
- lds r0, TASSState + TASS_SuppressKeyRandomisation
- tst r0
- brne 15f
- rcall RandomiseCMACKey
- ldiw Z, AuthenticationData + AD_CMACKey
- ldiw X, EEPROM_CMACKey
- ldi r16, 16
- rcall WriteEEPROMBlock
- ; Randomise the random part of the serial number.
- ldiw Z, EntropyHarvester +\
- EH_RandomData + EH_AUX_RANDOM_DATA_START_INDEX + 1
- ld r16, Z+
- ld r17, Z+
- add r17, r4
- ror r16
- st -Z, r16
- st -Z, r17
- swap r17
- add r16, r5
- add r16, r6
- andi r17, 0x0F
- ldiw Z, AuthenticationData
- ldd r0, Z + AD_SerialNumber + 0
- eor r0, r16
- std Z + AD_SerialNumber + 0, r0
- ldd r16, Z + AD_SerialNumber + 1
- andi r16, 0xF0
- or r16, r17
- std Z + AD_SerialNumber + 1, r16
- ; Save the new serial number.
- ldiw Z, AuthenticationData + AD_SerialNumber
- ldiw X, EEPROM_SerialNumber
- ldi r16, 4
- rcall WriteEEPROMBlock
- ; Update all of the random data while we're at it.
- ldiw Z, EntropyHarvester + EH_RandomData
- ldiw X, EEPROM_RandomData
- ldi r16, EH_MUTATION_INDEX_RANGE
- rcall WriteEEPROMBlock
- sts TASSState + TASS_SuppressKeyRandomisation, r2
- 15: rcall FullyUpdateEWLData
- clr r24
- lds r0, TASSState + TASS_SuppressKeyEncryption
- cpse r0, r1
- ldi r24, 1
- rcall BuildTeachMessage
- pop r24
- ldi r16, TeachMsgSize
- ldiw Z, TASSState
- std Y + G_Transmitter + Tx_NumBytesToSend, r16
- ldi r16, TX_STATE_BEGIN
- std Y + G_Transmitter + Tx_State, r16
- andi r24, ~(mTASK1_SEND_TEACH_MESSAGE)
- ldd r16, Z + TASS_NumTeachMessagesToSend
- sub r16, r2
- adc r16, r1
- std Z + TASS_NumTeachMessagesToSend, r16
- ifne
- ori r24, mTASK1_SEND_TEACH_MESSAGE
- std Y + G_TaskFlags1, r24
- rjmp main_Loop
- ; Max 122 cycles if the teach procedure is not performed.
- main_T2_TASSTasks_T3:
- rjmp main_Loop
- main_T3_SensorInputConditioningAndEntropyHarvesting:
- ; Debounce sensor inputs.
- ldd r24, Y + G_SecondarySensorIntegral
- clr r22
- sbis _SFR_IO_ADDR(PINB), INPUT_BIT_SECONDARY_SENSOR ; Active low!
- ser r22
- rcall DebounceSensor
- std Y + G_SecondarySensorIntegral, r24
- mov r16, r24
- ldd r24, Y + G_PrimarySensorIntegral
- clr r22
- sbis _SFR_IO_ADDR(PINB), INPUT_BIT_PRIMARY_SENSOR ; Active low!
- ser r22
- rcall DebounceSensor
- std Y + G_PrimarySensorIntegral, r24
- ; 51 cycles so far
- ; Set or clear the sensor state bits.
- ldd r18, Y + G_SensorsState
- mov r19, r18
- cp r24, r1
- ifeq
- andi r18, ~(1 << 0)
- cp r24, r3
- ifeq
- ori r18, (1 << 0)
- cp r16, r1
- ifeq
- andi r18, ~(1 << 1)
- cp r16, r3
- ifeq
- ori r18, (1 << 1)
- ldd r0, Y + G_SensorActivationSenses
- eor r18, r0
- std Y + G_SensorsState, r18
- ; 70 cycles so far
- cp r19, r18
- breq 2f
- ; The sensors state has changed.
- ; Harvest some entropy.
- rcall MutateRandomData ; 21 + 8 cycles
- std Y + G_CmdTxDelayRandomByte, r0
- ldiw Z, EntropyHarvester
- ; 105 cycles so far
- ; Lazily write the random data to EEPROM.
- ldd r0, Z + EH_EEPROMUpdatePending
- tst r0
- brne 1f
- ldd r16, Z + EH_MutationCounter
- inc r16
- std Z + EH_MutationCounter, r16
- andi r16, (1 << EH_UPDATE_COUNTER_BITS) - 1
- brne 2f
- std Z + EH_EEPROMUpdatePending, r2
- 1: sbic _SFR_IO_ADDR(EECR), EEPE
- rjmp 2f
- std Z + EH_EEPROMUpdatePending, r1
- ldd r16, Z + EH_EEPROMUpdateIndex
- subi r16, -EH_UPDATE_INDEX_ADVANCE
- andi r16, EH_MUTATION_INDEX_MASK
- std Z + EH_EEPROMUpdateIndex, r16
- adiw ZL, EH_RandomData
- add ZL, r16
- adc ZH, r1
- ldiw X, EEPROM_RandomData
- add XL, r16
- adc XH, r1
- ld r0, Z
- ; 138 cycles so far
- ldi r16, (0 << EEPM1) | (0 << EEPM0)
- out _SFR_IO_ADDR(EECR), r16
- out _SFR_IO_ADDR(EEARH), XH
- out _SFR_IO_ADDR(EEARL), XL
- out _SFR_IO_ADDR(EEDR), r0
- sbi _SFR_IO_ADDR(EECR), EEMPE
- sbi _SFR_IO_ADDR(EECR), EEPE ; The CPU is halted for 2 cycles.
- ; Max 147 cycles so far
- 2: rjmp main_Loop
- ; Max 149 cycles
- main_T4_SensorStateTxBurstsAndEWLUpdates:
- ldd r24, Y + G_TaskFlags1
- ldd r18, Y + G_SensorsState
- ldd r19, Y + G_TransmittedSensorsState
- ldiw Z, Globals + G_CmdTxRepeatSchedule
- cp r18, r19
- breq 1f
- std Y + G_TransmittedSensorsState, r18
- ; One of the sensors has changed state.
- ; Prepare the repeat schedule and submit a request
- ; for transmission right now.
- ; 10 cycles so far
- ldd r7, Y + G_CmdTxDelayRandomByte
- ldi r16, 1
- std Z + 5, r16
- ldi r16, 3
- std Z + 4, r16
- ldi r16, 8
- mov r17, r7
- andi r17, 0x03
- add r16, r17
- std Z + 3, r16
- ldi r16, 15
- sub r16, r17
- mov r17, r7
- lsr r17
- lsr r17
- andi r17, 0x03
- add r16, r17
- std Z + 2, r16
- ldi r16, 24
- sub r17, r17
- swap r7
- mov r17, r7
- andi r17, 0x03
- add r16, r17
- std Z + 1, r16
- ldi r16, 34
- sub r17, r17
- mov r17, r7
- lsr r17
- andi r17, 0x06
- add r16, r17
- std Z + 0, r16
- ldi r16, 6
- std Y + G_CmdTxNumRepeatsToSend, r16
- ori r24, mTASK1_SEND_CMD_MESSAGE
- ; 53 cycles so far
- rjmp 2f
- 1: ; Update the slow clock for the transmission repeat delay.
- ; 11 cycles so far
- ldd r0, Y + G_SlowClocks
- mov r7, r0
- bst r5, 3
- bld r0, bCLOCK_CMD_MSG_BURST
- std Y + G_SlowClocks, r0
- eor r7, r0
- bst r7, bCLOCK_CMD_MSG_BURST
- clr r0
- bld r0, 0
- ; See if a command transmission is already pending.
- sbrc r24, bTASK1_SEND_CMD_MESSAGE
- rjmp 2f
- ; Follow the transmission repeat schedule.
- ldd r16, Y + G_CmdTxNumRepeatsToSend
- dec r16
- brmi 2f
- add ZL, r16
- adc ZH, r1
- ld r7, Z
- sub r7, r0
- adc r7, r1
- st Z, r7
- brne 2f
- std Y + G_CmdTxNumRepeatsToSend, r16
- ori r24, mTASK1_SEND_CMD_MESSAGE
- ; 40 cycles so far
- 2: ; 40 or 55 cycles so far
- sbrs r24, bTASK1_SEND_CMD_MESSAGE
- rjmp 3f
- ; Send the command message as soon as the resources are available.
- ldd r16, Y + G_Transmitter + Tx_State
- cpi r16, TX_STATE_IDLE
- brne 3f
- ldd r16, Y + G_AuthenticationState
- cpi r16, AUTH_STATE_IDLE
- brne 3f
- ldd r16, Y + G_AESState
- cpi r16, AES_STATE_IDLE
- brne 3f
- ; Send the command now.
- andi r18, 0x03
- ori r18, 0x00 ; Just to make the hex file easy to edit
- ldd r19, Y + G_SoundIndices
- std Y + G_Transmitter + Tx_Data + CmdMsg_Command, r18
- std Y + G_Transmitter + Tx_Data + CmdMsg_Parameter, r19
- ldi r16, AUTH_STATE_CMDMSG_BEGIN
- std Y + G_AuthenticationState, r16
- andi r24, ~(mTASK1_SEND_CMD_MESSAGE)
- ; Max 83 cycles so far
- 3: std Y + G_TaskFlags1, r24
- rcall LazilyUpdateEWLData ; 66 cycles
- rjmp main_Loop
- ; Max 153 cycles
- main_T5_RefreshEEPROM:
- ldd r8, Y + G_SlowClocks
- mov r7, r8
- bst r6, 7 ; Cycling once every 524.29s
- bld r8, bCLOCK_EEPROM_REFRESH
- std Y + G_SlowClocks, r8
- com r8
- and r7, r8
- bst r7, bCLOCK_EEPROM_REFRESH
- brtc 1f
- sbic _SFR_IO_ADDR(EECR), EEPE
- rjmp 1f ; Busy! Better luck next time!
- ldd XL, Y + G_EEPROMRefreshCounter + 0
- ldd XH, Y + G_EEPROMRefreshCounter + 1
- add XL, r2
- adc XH, r1
- andi XH, 0x01
- std Y + G_EEPROMRefreshCounter + 0, XL
- std Y + G_EEPROMRefreshCounter + 1, XH
- rcall ReadEEPROMByte ; 18 cycles
- rcall WriteEEPROMByte ; 23 cycles
- 1: rjmp main_Loop
- ; Max 67 cycles
- main_T6:
- rjmp main_Loop
- main_T7:
- rjmp main_Loop
- ;-------------------------------------------------------------------------------
- ; Data in program memory
- ;-------------------------------------------------------------------------------
- ; As the AES round constant high bytes are easy to generate, they needn't be
- ; stored. Each round constant byte is the previous one shifted to the left
- ; and XORed with 0x1B if the shift set the carry flag. The RCon high byte for
- ; Round 1 is 0x01 and for Round 10, it is 0x36. If the advance occurs before
- ; each use, the start value should be 0x8D.
- ;
- ;PM_AES_RoundConstantBytes:
- ; .byte 0x8D, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40
- ; .byte 0x80, 0x1B, 0x36, 0x6C, 0xD8, 0xAB, 0x4D, 0x9A
- .balign 256
- PM_AES_SBox:
- .byte 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5
- .byte 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76
- .byte 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0
- .byte 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0
- .byte 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC
- .byte 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15
- .byte 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A
- .byte 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75
- .byte 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0
- .byte 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84
- .byte 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B
- .byte 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF
- .byte 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85
- .byte 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8
- .byte 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5
- .byte 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2
- .byte 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17
- .byte 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73
- .byte 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88
- .byte 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB
- .byte 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C
- .byte 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79
- .byte 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9
- .byte 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08
- .byte 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6
- .byte 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A
- .byte 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E
- .byte 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E
- .byte 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94
- .byte 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF
- .byte 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68
- .byte 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
- ;-------------------------------------------------------------------------------
- ; Globals in SRAM
- ;-------------------------------------------------------------------------------
- ;-------------------------------------------------------------------------------
- .section .bss
- ;-------------------------------------------------------------------------------
- Globals:
- .fill GSize
- TASSState:
- .fill TASSSize
- .balign 2
- TxRunLengthsRingBuffer:
- .fill TX_RING_BUFFER_INDEX_RANGE
- AES_Matrix_M:
- .fill 16
- AES_Matrix_K:
- .fill 16
- AES_Matrix_W:
- .fill 16
- AuthenticationData:
- .fill ADSize
- EWLState:
- .fill EWLSSize
- EntropyHarvester:
- .fill EHSize
- .balign 2
- VariablesEnd:
- ;-------------------------------------------------------------------------------
- .end
- ;-------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement