hardsploit_gui 2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +22 -0
  3. data/Rakefile +1 -0
  4. data/bin/hardsploit_gui +3 -0
  5. data/lib/Firmware/FPGA/I2C/I2C_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_I2C_INTERACT.rpd +0 -0
  6. data/lib/Firmware/FPGA/PARALLEL/NO_MUX_PARALLEL_MEMORY/HARDSPLOIT_FIRMWARE_FPGA_NO_MUX_PARALLEL_MEMORY.rpd +0 -0
  7. data/lib/Firmware/FPGA/SPI/SPI_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_SPI_INTERACT.rpd +0 -0
  8. data/lib/Firmware/FPGA/SWD/SWD_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_SWD_INTERACT.rpd +0 -0
  9. data/lib/Firmware/FPGA/TEST/TEST_INTERACT/HARDSPLOIT_FIRMWARE_FPGA_TEST_INTERACT.rpd +0 -0
  10. data/lib/Firmware/FPGA/VersionFPGA.rb +5 -0
  11. data/lib/Firmware/UC/HARDSPLOIT_FIRMWARE_UC.bin +0 -0
  12. data/lib/Firmware/UC/VersionUC.rb +12 -0
  13. data/lib/HardsploitAPI/HardsploitAPI.rb +134 -0
  14. data/lib/HardsploitAPI/HardsploitAPI_CONSTANT.rb +145 -0
  15. data/lib/HardsploitAPI/HardsploitAPI_FIRMWARE.rb +311 -0
  16. data/lib/HardsploitAPI/HardsploitAPI_I2C.rb +218 -0
  17. data/lib/HardsploitAPI/HardsploitAPI_NO_MUX_PARALLELE_MEMORY.rb +229 -0
  18. data/lib/HardsploitAPI/HardsploitAPI_SPI.rb +179 -0
  19. data/lib/HardsploitAPI/HardsploitAPI_TEST_INTERACT.rb +98 -0
  20. data/lib/HardsploitAPI/HardsploitAPI_USB_COMMUNICATION.rb +149 -0
  21. data/lib/HardsploitAPI/LICENSE.txt +674 -0
  22. data/lib/HardsploitAPI/README.md +22 -0
  23. data/lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb +249 -0
  24. data/lib/HardsploitAPI/SWD/HardsploitAPI_SWD_DEBUG.rb +102 -0
  25. data/lib/HardsploitAPI/SWD/HardsploitAPI_SWD_MEM_AP.rb +78 -0
  26. data/lib/HardsploitAPI/SWD/HardsploitAPI_SWD_STM32.rb +104 -0
  27. data/lib/HardsploitAPI/TRADEMARK +3 -0
  28. data/lib/LICENSE.txt +674 -0
  29. data/lib/README.md +22 -0
  30. data/lib/TRADEMARK +3 -0
  31. data/lib/class/Chip_editor.rb +448 -0
  32. data/lib/class/Command_editor.rb +268 -0
  33. data/lib/class/Command_table.rb +239 -0
  34. data/lib/class/Console.rb +28 -0
  35. data/lib/class/Export_manager.rb +124 -0
  36. data/lib/class/Firmware.rb +29 -0
  37. data/lib/class/Generic_commands.rb +275 -0
  38. data/lib/class/HardsploitGUI.rb +462 -0
  39. data/lib/class/I2C/I2c_command.rb +48 -0
  40. data/lib/class/I2C/I2c_export.rb +121 -0
  41. data/lib/class/I2C/I2c_import.rb +92 -0
  42. data/lib/class/I2C/I2c_settings.rb +117 -0
  43. data/lib/class/PARALLEL/Parallel_export.rb +146 -0
  44. data/lib/class/PARALLEL/Parallel_import.rb +88 -0
  45. data/lib/class/PARALLEL/Parallel_settings.rb +102 -0
  46. data/lib/class/SPI/Spi_export.rb +141 -0
  47. data/lib/class/SPI/Spi_import.rb +112 -0
  48. data/lib/class/SPI/Spi_settings.rb +90 -0
  49. data/lib/class/Wire_helper.rb +246 -0
  50. data/lib/db/associations.rb +125 -0
  51. data/lib/db/hs.db +0 -0
  52. data/lib/gui/gui_chip_editor.rb +355 -0
  53. data/lib/gui/gui_chip_management.rb +372 -0
  54. data/lib/gui/gui_command_editor.rb +218 -0
  55. data/lib/gui/gui_export_manager.rb +93 -0
  56. data/lib/gui/gui_generic_commands.rb +164 -0
  57. data/lib/gui/gui_generic_export.rb +148 -0
  58. data/lib/gui/gui_generic_import.rb +126 -0
  59. data/lib/gui/gui_i2c_command.rb +115 -0
  60. data/lib/gui/gui_i2c_settings.rb +201 -0
  61. data/lib/gui/gui_parallel_settings.rb +194 -0
  62. data/lib/gui/gui_spi_import.rb +126 -0
  63. data/lib/gui/gui_spi_settings.rb +187 -0
  64. data/lib/gui/gui_wire_helper.rb +99 -0
  65. data/lib/gui_designer/gui_chip_editor.ui +553 -0
  66. data/lib/gui_designer/gui_chip_management.ui +842 -0
  67. data/lib/gui_designer/gui_command_editor.ui +347 -0
  68. data/lib/gui_designer/gui_export_manager.ui +115 -0
  69. data/lib/gui_designer/gui_generic_commands.ui +258 -0
  70. data/lib/gui_designer/gui_generic_export.ui +179 -0
  71. data/lib/gui_designer/gui_generic_import.ui +142 -0
  72. data/lib/gui_designer/gui_i2c_command.ui +145 -0
  73. data/lib/gui_designer/gui_i2c_settings.ui +261 -0
  74. data/lib/gui_designer/gui_parallel_settings.ui +244 -0
  75. data/lib/gui_designer/gui_processing.ui +81 -0
  76. data/lib/gui_designer/gui_spi_settings.ui +321 -0
  77. data/lib/gui_designer/gui_wire_helper.ui +117 -0
  78. data/lib/hardsploit.rb +122 -0
  79. data/lib/images/search.png +0 -0
  80. data/lib/logs/error.log +0 -0
  81. metadata +236 -0
@@ -0,0 +1,22 @@
1
+ # Hardsploit
2
+
3
+ The essential security auditing tool for Internet of Things devices you'll need in your toolbox
4
+
5
+ ### [GO TO HARDSPLOIT](http://www.hardsploit.io)
6
+
7
+ TO LEARN ABOUT IT
8
+
9
+ ### [GO TO SHOP](https://www.shop-hardsploit.com)
10
+ TO BUY
11
+
12
+ ### [GO TO WIKI](https://github.com/OPALESECURITY/hardsploit-api/wiki)
13
+
14
+ TO UNDERSTAND HOW USE IT
15
+
16
+ ### [GO TO FORUM](http://forum.hardsploit.io)
17
+
18
+ FOR SUPPORT / HELP
19
+
20
+ ### [GO TO BUG TRACKER](https://github.com/OPALESECURITY/hardsploit-api/issues)
21
+
22
+ FOR BUGS OR IMPROVEMENTS
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/ruby
2
+ #===================================================
3
+ # Hardsploit API - By Opale Security
4
+ # www.opale-security.com || www.hardsploit.io
5
+ # License: GNU General Public License v3
6
+ # License URI: http://www.gnu.org/licenses/gpl.txt
7
+ #===================================================
8
+ require_relative 'HardsploitAPI_SWD_DEBUG'
9
+ require_relative 'HardsploitAPI_SWD_STM32'
10
+
11
+ class HardsploitAPI
12
+ attr_accessor :debugPort
13
+ attr_accessor :stm32
14
+
15
+ def runSWD
16
+ @debugPort = SWD_DEBUG_PORT.new(self)
17
+ @stm32 = SWD_STM32.new(debugPort)
18
+
19
+ resetSWD()
20
+ # Cortex M4 0x410FC241
21
+ # Cortex M3 411FC231
22
+ end
23
+
24
+ def obtainCodes
25
+ resetSWD()
26
+ code = {
27
+ :DebugPortId => debugPort.idcode(),
28
+ :AccessPortId => stm32.ahb.idcode(),
29
+ :CpuId => stm32.ahb.readWord(0xE000ED00),
30
+ :DeviceId => stm32.ahb.readWord(0x1FFFF7E8)
31
+ }
32
+ return code
33
+ end
34
+
35
+
36
+ def writeFlash(path)
37
+ resetSWD()
38
+ dataWrite = IO.binread(path)
39
+ dataWrite = dataWrite.unpack("C*")
40
+ puts "Halting Processor"
41
+ stm32.halt()
42
+ puts "Erasing Flash"
43
+ stm32.flashUnlock()
44
+ stm32.flashErase()
45
+ puts "Programming Flash"
46
+ stm32.flashProgram()
47
+ time = Time.new
48
+ stm32.flashWrite(0x08000000, dataWrite)
49
+ time = Time.new - time
50
+ puts "Write #{((dataWrite.size/time)).round(2)}Bytes/s #{(dataWrite.size)}Bytes in #{time.round(4)} s"
51
+ stm32.flashProgramEnd()
52
+ puts "Resetting"
53
+ stm32.sysReset()
54
+ puts "Start"
55
+ stm32.unhalt
56
+ end
57
+
58
+ def eraseFlash
59
+ puts 'Erase'
60
+ stm32.flashErase()
61
+ end
62
+
63
+ def dumpFlash(path)
64
+ resetSWD()
65
+ #DUMP FLASH MEMORY TO A FILE
66
+ @stm32.halt
67
+ flash_size = (stm32.ahb.readWord(0x1ffff7e0) & 0xFFFF)
68
+ puts "Flash size : #{(flash_size) } KB"
69
+ puts "Dump flash"
70
+ time = Time.new
71
+ data = @stm32.flashRead(0x08000000,(flash_size*1024))
72
+ time = Time.new - time
73
+ puts "DUMP #{((data.size/time)).round(2)}Bytes/s #{(data.size)}Bytes in #{time.round(4)} s"
74
+ IO.binwrite(path, data.pack('C*'))
75
+ puts "Finish dump"
76
+ end
77
+
78
+ def writeSWD(ap,register,data)
79
+ packet = Array.new
80
+ packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb
81
+ packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb
82
+ packet.push HardsploitAPI.lowByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
83
+ packet.push HardsploitAPI.highByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
84
+
85
+ packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO
86
+
87
+ packet.push 0x10 #Write mode
88
+
89
+ packet.push (calcOpcode(ap, register, false)) #Send Request
90
+
91
+ packet.push ((data & 0xFF) >> 0)
92
+ packet.push ((data & 0xFF00) >> 8 )
93
+ packet.push ((data & 0xFF0000) >> 16 )
94
+ packet.push ((data & 0xFF000000) >> 24 )
95
+
96
+ result = sendAndReceiveDATA(packet,1000)
97
+
98
+ if result.class == Array then
99
+ if result.size == 1 + 4 then #receive ACK
100
+ if result[4] == 1 then
101
+ return true
102
+ elsif result[4] == 2 then
103
+ raise "WAIT response"
104
+ elsif result[4] == 4 then
105
+ raise "FAULT response"
106
+ else
107
+ raise "WRITE ERROR #{result[4]}"
108
+ end
109
+ else
110
+ raise "Error during writing}"
111
+ end
112
+ else # Receive and error
113
+ raise "Error during writing, timeout "
114
+ end
115
+
116
+ return false
117
+ end
118
+
119
+ def writeBlockAP(data)
120
+ if data.size > 8000 then
121
+ raise "data is too big > 8000"
122
+ end
123
+
124
+ packet = Array.new
125
+ packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb
126
+ packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb
127
+ packet.push HardsploitAPI.lowByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
128
+ packet.push HardsploitAPI.highByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
129
+
130
+ packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO
131
+ packet.push 0xBB #Write ap
132
+ packet.push *data
133
+
134
+ result = sendAndReceiveDATA(packet,1000)
135
+ if result.class == Array then
136
+ if result.size == 1 + 4 then #receive ACK
137
+ if result[4] == 1 then
138
+ return true
139
+ elsif result[4] == 2 then
140
+ raise "WAIT response"
141
+ elsif result[4] == 4 then
142
+ raise "FAULT response"
143
+ else
144
+ raise "WRITE ERROR #{result[4]}"
145
+ end
146
+ else
147
+ raise "Error during writing"
148
+ end
149
+ else # Receive and error
150
+ raise "Error during writing, timeout "
151
+ end
152
+ return false
153
+ end
154
+
155
+
156
+ def readBlockAP(size)
157
+ packet = Array.new
158
+ packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb
159
+ packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb
160
+ packet.push HardsploitAPI.lowByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
161
+ packet.push HardsploitAPI.highByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
162
+
163
+ packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO
164
+
165
+ packet.push 0xAA #Read mode
166
+ packet.push HardsploitAPI.lowByte(size)
167
+ packet.push HardsploitAPI.highByte(size)
168
+
169
+ result = sendAndReceiveDATA(packet,1000)
170
+ if result.class == Array then
171
+ if result.size >= 4 then #Receive read + 4bytes for header
172
+ return result.drop(4)
173
+ else
174
+ raise "Receive just Header where is the data ? "
175
+ end
176
+ else # Receive and error
177
+ raise "Error during reading timeout or ACK issue "
178
+ end
179
+ end
180
+
181
+ def readSWD(ap,register)
182
+ packet = Array.new
183
+ packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb
184
+ packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb
185
+ packet.push HardsploitAPI.lowByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
186
+ packet.push HardsploitAPI.highByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
187
+
188
+ packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO
189
+
190
+ packet.push 0x11 #Read mode
191
+ packet.push(calcOpcode(ap,register, true)) #Send Request
192
+
193
+ result = sendAndReceiveDATA(packet,1000)
194
+ if result.class == Array then
195
+ if result.size == 4 + 4 then #Receive read + 4bytes for header
196
+ convert = (result[7] << 24) + (result[6] << 16) + (result[5] << 8 ) + result[4]
197
+ return convert
198
+ elsif result.size == 4+1 then #receive ACK
199
+ raise "Read error ACK : #{result[4]}"
200
+ else
201
+ raise "Error during reading"
202
+ end
203
+ else # Receive and error
204
+ raise "Error during reading timeout "
205
+ end
206
+ end
207
+
208
+
209
+ #Return array with 1 byte for ACK
210
+ #Return 32bits integer for data read here is Core ID
211
+ #Raise if error
212
+ def resetSWD
213
+ packet = Array.new
214
+ packet.push 0 #low byte of lenght of trame refresh automaticly before send by usb
215
+ packet.push 0 #high byte of lenght of trame refresh automaticly before send by usb
216
+ packet.push HardsploitAPI.lowByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
217
+ packet.push HardsploitAPI.highByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
218
+
219
+ packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO
220
+
221
+ packet.push 0x00 #Reset mode
222
+
223
+ result = sendAndReceiveDATA(packet,1000)
224
+ if result.class == Array then
225
+ if result.size == 4 + 4 then #Receive read + 4bytes for header
226
+ convert = (result[7] << 24) + (result[6] << 16) + (result[5] << 8 ) + result[4]
227
+ return convert
228
+ elsif result.size == 4 +1 then #reveice ACK
229
+ raise "ERROR ACK #{result[4]}"
230
+ else
231
+ raise "Error during reading ICCODE result != 4"
232
+ end
233
+ else # Receive and error
234
+ raise "Error during reading ICCODE timeout "
235
+ end
236
+ end
237
+
238
+
239
+ def calcOpcode (ap, register, read)
240
+ opcode = 0x00
241
+ (ap ? opcode |= 0x40 : opcode |= 0x00)
242
+ (read ? opcode |= 0x20 : opcode |= 0x00)
243
+ opcode = opcode | ((register & 0x01) << 4) | ((register & 0x02) << 2) #Addr AP DP bit 2..3
244
+ opcode = opcode | (((opcode & 0x78).to_s(2).count('1').odd? ? 1 : 0) << 2) #0x78 mask to take only read ap and register to process parity bit
245
+ opcode = opcode | 0x81 #Start and Park Bit
246
+ #puts "OpCode #{opcode.to_s(16)}"
247
+ return opcode
248
+ end
249
+ end
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/ruby
2
+ #===================================================
3
+ # Hardsploit API - By Opale Security
4
+ # www.opale-security.com || www.hardsploit.io
5
+ # License: GNU General Public License v3
6
+ # License URI: http://www.gnu.org/licenses/gpl.txt
7
+ #===================================================
8
+ class SWD_DEBUG_PORT
9
+
10
+ def initialize(hardAPI)
11
+ @HardAPI = hardAPI
12
+ @HardAPI.startFPGA
13
+ sleep(0.5)
14
+ @HardAPI.resetSWD
15
+ # read the IDCODE
16
+ # if HardAPI.resetSWD() != 0x1ba01477 then
17
+ # raise "warning: unexpected idcode"
18
+ # else
19
+ # puts "MCU DETECTED"
20
+ # end
21
+ abort(1,1,1,1,1)
22
+ select(0,0)
23
+ # power shit up
24
+ puts "Power shit up"
25
+ @HardAPI.writeSWD(FALSE, 1, 0x54000000)
26
+ if (status() >> 24) != 0xF4 then
27
+ raise "error powering up system"
28
+ exit(0)
29
+ else
30
+ puts "POWERING UP SYTEM OK"
31
+ end
32
+ #get the SELECT register to a known state
33
+ select(0,0)
34
+ @curAP = 0
35
+ @curBank = 0
36
+ end
37
+
38
+ def getAPI
39
+ return @HardAPI
40
+ end
41
+
42
+ def idcode
43
+ return @HardAPI.readSWD(FALSE, 0)
44
+ end
45
+
46
+ def abort (orunerr, wdataerr, stickyerr, stickycmp, dap)
47
+ value = 0x00000000
48
+ (orunerr ? value |= 0x10 : value |= 0x00)
49
+ (wdataerr ? value |= 0x08 : value |= 0x00)
50
+ (stickyerr ? value |= 0x04 : value |= 0x00)
51
+ (stickycmp ? value |= 0x02 : value |= 0x00)
52
+ (dap ? value |= 0x01 : value |= 0x00)
53
+ @HardAPI.writeSWD(FALSE, 0, value)
54
+ end
55
+
56
+ def status
57
+ val= @HardAPI.readSWD(FALSE,1)
58
+ return val
59
+ end
60
+
61
+ def control (trnCount = 0, trnMode = 0, maskLane = 0, orunDetect = 0)
62
+ value = 0x54000000
63
+ value = value | ((trnCount & 0xFFF) << 12)
64
+ value = value | ((maskLane & 0x00F) << 8)
65
+ value = value | ((trnMode & 0x003) << 2)
66
+ (orunDetect ? value |= 0x01 : value |= 0x00)
67
+ @HardAPI.writeSWD(False, 1, value)
68
+ end
69
+
70
+ def select (apsel, apbank)
71
+ value = 0x00000000
72
+ value = value | ((apsel & 0xFF) << 24)
73
+ value = value | ((apbank & 0x0F) << 4)
74
+ @HardAPI.writeSWD(FALSE, 2, value)
75
+ end
76
+
77
+
78
+ def readRB
79
+ return @HardAPI.readSWD(FALSE, 3)
80
+ end
81
+ def readAP ( apsel, address)
82
+ adrBank = (address >> 4) & 0xF
83
+ adrReg = (address >> 2) & 0x3
84
+ if apsel != @curAP or adrBank != @curBank then
85
+ select(apsel, adrBank)
86
+ @curAP = apsel
87
+ @curBank = adrBank
88
+ end
89
+ return @HardAPI.readSWD(TRUE, adrReg)
90
+ end
91
+
92
+ def writeAP (apsel, address, data)
93
+ adrBank = (address >> 4) & 0xF
94
+ adrReg = (address >> 2) & 0x3
95
+ if apsel != @curAP or adrBank != @curBank then
96
+ select(apsel, adrBank)
97
+ @curAP = apsel
98
+ @curBank = adrBank
99
+ end
100
+ @HardAPI.writeSWD(TRUE, adrReg, data)
101
+ end
102
+ end
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/ruby
2
+ #===================================================
3
+ # Hardsploit API - By Opale Security
4
+ # www.opale-security.com || www.hardsploit.io
5
+ # License: GNU General Public License v3
6
+ # License URI: http://www.gnu.org/licenses/gpl.txt
7
+ #===================================================
8
+
9
+ class SWD_MEM_AP
10
+
11
+ def initialize( dp, apsel)
12
+ @dp = dp
13
+ @apsel = apsel
14
+ csw(1,2) # 32-bit auto-incrementing addressing
15
+ end
16
+
17
+ def csw ( addrInc, size)
18
+ @dp.readAP(@apsel, 0x00)
19
+ val = @dp.readRB() & 0xFFFFFF00
20
+ @dp.writeAP(@apsel, 0x00, val + (addrInc << 4) + size)
21
+ end
22
+ def idcode
23
+ @dp.readAP(@apsel, 0xFC)
24
+ return @dp.readRB()
25
+ end
26
+ def readWord (adr)
27
+ @dp.writeAP(@apsel, 0x04, adr)
28
+ @dp.readAP(@apsel, 0x0C)
29
+ return @dp.readRB()
30
+ end
31
+ def writeWord (adr, data)
32
+ @dp.writeAP(@apsel, 0x04, adr)
33
+ @dp.writeAP(@apsel, 0x0C, data)
34
+ return @dp.readRB()
35
+ end
36
+ def readBlock ( adr, count)#1K boundaries and return 4K of data word alignement
37
+ if count < 1 then
38
+ raise "readBlock error : count must be >= 1"
39
+ end
40
+ if count > 1024 then
41
+ raise "readBlock error : count must be <= 1024 "
42
+ end
43
+ csw(1, 2) # 32-bit single-incrementing addressing
44
+ @dp.writeAP(@apsel, 0x04, adr)
45
+ vals = Array.new
46
+ @dp.readAP(@apsel, 0x0C) #For the first byte
47
+ vals.push(*@dp.getAPI.readBlockAP(count-1)) #Hardcoded function to increase speed of read block
48
+ return vals
49
+ end
50
+
51
+ # def writeBlockNonInc (adr, data)
52
+ # self.csw(0, 2) # 32-bit non-incrementing addressing
53
+ # for val in data
54
+ # @dp.writeAP(@apsel, 0x04, adr)
55
+ # @dp.writeAP(@apsel, 0x0C, val)
56
+ # end
57
+ # self.csw(1, 2) # 32-bit auto-incrementing addressing
58
+ # end
59
+
60
+ def writeBlock (adr, data) #1K boundaries
61
+ @dp.writeAP(@apsel, 0x04, adr)
62
+ puts "writeBlock #{adr.to_s(16)}"
63
+
64
+ @dp.getAPI.writeBlockAP(data)
65
+ # for i in (0..data.size-1).step(4)
66
+ # @dp.writeAP(@apsel, 0x0C, data[i].to_i + (data[i+1].to_i << 8) + (data[i+2].to_i << 16)+ (data[i+3].to_i << 24))
67
+ # end
68
+ end
69
+
70
+ def writeHalfs (adr, data)
71
+ self.csw(2, 1) # 16-bit packed-incrementing addressing
72
+ @dp.writeAP(@apsel, 0x04, adr)
73
+ for val in data
74
+ sleep(0.001)
75
+ @dp.writeAP(@apsel, 0x0C, val)
76
+ end
77
+ end
78
+ end