rp2040_hal_2.2.1_dd57b8f8/src/drivers/rp-pio-encoding.ads

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
--
--  Copyright (C) 2022 Jeremy Grosser <jeremy@synack.me>
--
--  SPDX-License-Identifier: BSD-3-Clause
--
with Ada.Unchecked_Conversion;

package RP.PIO.Encoding
   with Preelaborate
is

   type JMP_Condition is
      (Always,
       Scratch_X_Zero,              --  !X
       Scratch_X_Nonzero_Decrement, --  X--
       Scratch_Y_Zero,              --  !Y
       Scratch_Y_Nonzero_Decrement, --  Y--
       X_Notequal_Y,                --  X!=Y
       Input_Pin,                   --  PIN
       OSRE_Not_Empty)              --  !OSRE
   with Size => 3;

   type JMP is record
      Opcode         : HAL.UInt3 := 2#000#;
      Delay_Sideset  : HAL.UInt5 := 0;
      Condition      : JMP_Condition := Always;
      Address        : HAL.UInt5 := 0;
   end record
      with Size => 16;
   for JMP use record
      Opcode         at 0 range 13 .. 15;
      Delay_Sideset  at 0 range 8 .. 12;
      Condition      at 0 range 5 .. 7;
      Address        at 0 range 0 .. 4;
   end record;

   type WAIT_Source is
      (GPIO, PIN, WAIT_IRQ)
   with Size => 2;

   type WAIT is record
      Opcode         : HAL.UInt3 := 2#001#;
      Delay_Sideset  : HAL.UInt5 := 0;
      Polarity       : Boolean := False;
      Source         : WAIT_Source := GPIO;
      Index          : HAL.UInt5 := 0;
   end record
      with Size => 16;
   for WAIT use record
      Opcode         at 0 range 13 .. 15;
      Delay_Sideset  at 0 range 8 .. 12;
      Polarity       at 0 range 7 .. 7;
      Source         at 0 range 5 .. 6;
      Index          at 0 range 0 .. 4;
   end record;

   type SHIFT_IN_Source is
      (PINS, X, Y, ZERO, ISR, OSR)
   with Size => 3;
   for SHIFT_IN_Source use
      (PINS => 2#000#,
       X    => 2#001#,
       Y    => 2#010#,
       ZERO => 2#011#,
       ISR  => 2#110#,
       OSR  => 2#111#);

   type SHIFT_IN is record
      Opcode         : HAL.UInt3 := 2#010#;
      Delay_Sideset  : HAL.UInt5 := 0;
      Source         : SHIFT_IN_Source := PINS;
      Bit_Count      : HAL.UInt5; --  0 = 32
   end record
      with Size => 16;
   for SHIFT_IN use record
      Opcode         at 0 range 13 .. 15;
      Delay_Sideset  at 0 range 8 .. 12;
      Source         at 0 range 5 .. 7;
      Bit_Count      at 0 range 0 .. 4;
   end record;

   type SHIFT_OUT_Destination is
      (PINS, X, Y, DISCARD, PINDIRS, PC, ISR, EXEC)
   with Size => 3;
   for SHIFT_OUT_Destination use
      (PINS    => 2#000#,
       X       => 2#001#,
       Y       => 2#010#,
       DISCARD => 2#011#,
       PINDIRS => 2#100#,
       PC      => 2#101#,
       ISR     => 2#110#,
       EXEC    => 2#111#);
   type SHIFT_OUT is record
      Opcode         : HAL.UInt3 := 2#011#;
      Delay_Sideset  : HAL.UInt5 := 0;
      Destination    : SHIFT_OUT_Destination := PINS;
      Bit_Count      : HAL.UInt5; --  0 = 32
   end record
      with Size => 16;
   for SHIFT_OUT use record
      Opcode         at 0 range 13 .. 15;
      Delay_Sideset  at 0 range 8 .. 12;
      Destination    at 0 range 5 .. 7;
      Bit_Count      at 0 range 0 .. 4;
   end record;

   type PUSH is record
      Opcode         : HAL.UInt3 := 2#100#;
      Delay_Sideset  : HAL.UInt5 := 0;
      Opcode_2       : Boolean := False;
      If_Full        : Boolean := False;
      Block          : Boolean := False;
      Opcode_3       : HAL.UInt5 := 0;
   end record
      with Size => 16;
   for PUSH use record
      Opcode         at 0 range 13 .. 15;
      Delay_Sideset  at 0 range 8 .. 12;
      Opcode_2       at 0 range 7 .. 7;
      If_Full        at 0 range 6 .. 6;
      Block          at 0 range 5 .. 5;
      Opcode_3       at 0 range 0 .. 4;
   end record;

   type PULL is record
      Opcode         : HAL.UInt3 := 2#100#;
      Delay_Sideset  : HAL.UInt5 := 0;
      Opcode_2       : Boolean := True;
      If_Empty       : Boolean := False;
      Block          : Boolean := False;
      Opcode_3       : HAL.UInt5 := 0;
   end record
      with Size => 16;
   for PULL use record
      Opcode         at 0 range 13 .. 15;
      Delay_Sideset  at 0 range 8 .. 12;
      Opcode_2       at 0 range 7 .. 7;
      If_Empty       at 0 range 6 .. 6;
      Block          at 0 range 5 .. 5;
      Opcode_3       at 0 range 0 .. 4;
   end record;

   type MOV_Target is
      (PINS, X, Y, EXEC, PC, ISR, OSR)
   with Size => 3;
   for MOV_Target use
      (PINS => 2#000#,
       X    => 2#001#,
       Y    => 2#010#,
       EXEC => 2#100#,
       PC   => 2#101#,
       ISR  => 2#110#,
       OSR  => 2#111#);

   type MOV_Operation is
      (None, Invert, Bit_Reverse)
   with Size => 2;

   type MOV is record
      Opcode         : HAL.UInt3 := 2#101#;
      Delay_Sideset  : HAL.UInt5 := 0;
      Destination    : MOV_Target := PINS;
      Operation      : MOV_Operation := None;
      Source         : MOV_Target := PINS;
   end record
      with Size => 16;
   for MOV use record
      Opcode         at 0 range 13 .. 15;
      Delay_Sideset  at 0 range 8 .. 12;
      Destination    at 0 range 5 .. 7;
      Operation      at 0 range 3 .. 4;
      Source         at 0 range 0 .. 2;
   end record;

   type IRQ is record
      Opcode         : HAL.UInt3 := 2#110#;
      Delay_Sideset  : HAL.UInt5 := 0;
      Opcode_2       : Boolean := False;
      Clear          : Boolean := False;
      Wait           : Boolean := False;
      Index          : HAL.UInt5;
   end record
      with Size => 16;
   for IRQ use record
      Opcode         at 0 range 13 .. 15;
      Delay_Sideset  at 0 range 8 .. 12;
      Opcode_2       at 0 range 7 .. 7;
      Clear          at 0 range 6 .. 6;
      Wait           at 0 range 5 .. 5;
      Index          at 0 range 0 .. 4;
   end record;

   type SET_Destination is
      (PINS, X, Y, PINDIRS)
   with Size => 3;
   for SET_Destination use
      (PINS    => 2#000#,
       X       => 2#001#,
       Y       => 2#010#,
       PINDIRS => 2#100#);

   type SET is record
      Opcode         : HAL.UInt3 := 2#111#;
      Delay_Sideset  : HAL.UInt5 := 0;
      Destination    : SET_Destination := PINS;
      Data           : HAL.UInt5 := 0;
   end record
      with Size => 16;
   for SET use record
      Opcode         at 0 range 13 .. 15;
      Delay_Sideset  at 0 range 8 .. 12;
      Destination    at 0 range 5 .. 7;
      Data           at 0 range 0 .. 4;
   end record;

   function Encode is new Ada.Unchecked_Conversion (JMP, PIO_Instruction);
   function Encode is new Ada.Unchecked_Conversion (WAIT, PIO_Instruction);
   function Encode is new Ada.Unchecked_Conversion (SHIFT_IN, PIO_Instruction);
   function Encode is new Ada.Unchecked_Conversion (SHIFT_OUT, PIO_Instruction);
   function Encode is new Ada.Unchecked_Conversion (PUSH, PIO_Instruction);
   function Encode is new Ada.Unchecked_Conversion (PULL, PIO_Instruction);
   function Encode is new Ada.Unchecked_Conversion (MOV, PIO_Instruction);
   function Encode is new Ada.Unchecked_Conversion (IRQ, PIO_Instruction);
   function Encode is new Ada.Unchecked_Conversion (SET, PIO_Instruction);

end RP.PIO.Encoding;