# FPGA Manager

FpgaManager为上层软件提供访问FPGA功能的服务,它是一个单例,并提供了一组线程安全的、同步的FPGA服务接口。

uml diagram

FpgaManager提供两种访问寄存器的方式,通过名字或地址,名字和地址一一对应。FPGA寄存器有些是可读的,有些是可写的,有些是可读可写的,这些访问权限会通过一个内部表进行控制。

FPGA寄存器地址定义如下:

typedef enum {
  // sdram registers
  REG_SDRAM_ADDR_LO       = 0x0000,
  REG_SDRAM_ADDR_HI       = 0x0001,
  REG_SDRAM_PIPE          = 0x0002,

  REG_SEGMENT_NUM         = 0x0003,

  // b0 = 1, start scan; b0 = 0, stop scan; b1 = 1, scan complete
  REG_SCAN                = 0x0004,

  // switche[1]: 1 - on(open loop); 0 - off(closed loop), default 0
  REG_SWITCH_RF_OPEN_LOOP = 0x0005,

  // DAC for KV
  REG_DAC_P5KV            = 0x0006,
  REG_DAC_N5KV            = 0x0007,
  REG_DAC_N2KV            = 0x0008,

  // switche[2-4]: 1 - on; 0 - off
  REG_SWITCH_SOURCE       = 0x0009,
  REG_SWITCH_DETECTOR     = 0x000A,
  REG_SWITCH_POLARITY_NEG = 0x000B,

  // DAC for HV
  REG_DAC_FLOAT01         = 0x000C,
  REG_DAC_FLOAT02         = 0x000D,
  REG_DAC_GATE01          = 0x000E,
  REG_DAC_GATE02          = 0x000F,
  REG_DAC_GATE03          = 0x0010,

  // code = F/25000000*2^32
  // *** MUST*** config low 16 bits first
  REG_DDS_RF1_FREQ_LO     = 0x0011,
  REG_DDS_RF1_FREQ_HI     = 0x0012,
  // code = V/3.0*65536
  REG_DAC_RF1_AMP         = 0x0013,

  // code = F/25000000*2^32
  // *** MUST*** config low 16 bits first
  REG_DDS_RF2_FREQ_LO     = 0x0014,
  REG_DDS_RF2_FREQ_HI     = 0x0015,
  // code = V/3.0*65536
  REG_DAC_RF2_AMP         = 0x0016,

  // code = F/25000000*2^32
  // *** MUST*** config low 16 bits first
  REG_DDS_AC1_FREQ_LO     = 0x0017,
  REG_DDS_AC1_FREQ_HI     = 0x0018,
  // code = (V/4.5+1)*32768
  REG_DAC_AC1_AMP         = 0x0019,

  // code = F/25000000*2^32
  // *** MUST*** config low 16 bits first
  REG_DDS_AC2_FREQ_LO     = 0x001A,
  REG_DDS_AC2_FREQ_HI     = 0x001B,
  // code = (V/4.5+1)*32768
  REG_DAC_AC2_AMP         = 0x001C,
  REG_DAC_COUNTING_THRESHOLD   = 0x001D, // 0 ~ 65535

  // switche[5-15]: 1 - on(open loop); 0 - off(closed loop), default 0
  REG_SWITCH_DAPI              = 0x001E,  // 24V
  REG_SWITCH_S1                = 0x001E,  // 24V
  REG_SWITCH_ROUGH             = 0x001F,  // 24V
  REG_SWITCH_S2                = 0x001F,  // 24V
  REG_SWITCH_TURBO             = 0x0020,  // 24V
  REG_SWITCH_S3                = 0x0020,  // 24V
  REG_SWITCH_S4                = 0x0021,  // 24V
  REG_SWITCH_S5                = 0x0022,  // 5V
  REG_SWITCH_S6                = 0x0023,  // 3.3V
  REG_SWITCH_S7                = 0x0024,  // 3.3V
  REG_SWITCH_TRIGGER_OUT1      = 0x0025,  // 3.3V
  REG_SWITCH_S8                = 0x0025,  // 3.3V
  REG_SWITCH_HV                = 0x0026,
  REG_SWITCH_KV                = 0x0027,

  // divide = 20Ksps/rate, for pressure gauge sample rate
  REG_GAUGE_SAMPLE_RATE_DIVIDE = 0x0028,

  // switche[16-18]: 1 - on; 0 - off, default 0
  REG_SWITCH_SWIFT1            = 0x0029,  // default off
  REG_SWITCH_SWIFT2            = 0x002A,  // default off
  REG_SWITCH_COUNTING_MODE     = 0x002B,  // default off

  // code = phase(degree)/360*2^32
  REG_DDS_AC1_PHASE_LO         = 0x002C,  // default off
  REG_DDS_AC1_PHASE_HI         = 0x002D,  // default off
  REG_DDS_AC2_PHASE_LO         = 0x002E,  // default off
  REG_DDS_AC2_PHASE_HI         = 0x002F,  // default off

  REG_SWITCH_VALVE1            = 0x0030,  // 24V
  REG_SWITCH_VALVE2            = 0x0031,  // 24V
  REG_FILT_MODE                = 0x0032,  // default 0

  // ADC regsiters
  // V = code/65536*3.0
  REG_ADC_RF1_AMP              = 0x0100,
  REG_ADC_RF2_AMP              = 0x0101,
  REG_ADC_AC1_AMP              = 0x0102,
  REG_ADC_AC2_AMP              = 0x0103,

  // V = (code/65536*3.0-1.0)/2*96
  REG_ADC_GATE1                = 0x0104,
  REG_ADC_GATE2                = 0x0105,
  // V = code/65536*3.0*(400000/40.2+1)
  REG_ADC_P5KV                 = 0x0106,
  REG_ADC_GATE3                = 0x0107,
  /// REG_ADC_BASE_TEMP        = 0x0108, // Deprecated
  REG_ADC_IESI                 = 0x0109,
  // V = code/65536*3.0/80.6*40.2*(400000/20.1+1)
  REG_ADC_N5KV                 = 0x0110,
  /// REG_ADC_KV_TEMP          = 0x0111, // Deprecated
  // V = code/65536*3.0/200*100*(100000/50+1)
  REG_ADC_N2KV                 = 0x0112,

  // V = (code/65536*3.0-1.0)/2*96
  REG_ADC_TRAP1                = 0x0113,
  REG_ADC_TRAP2                = 0x0114,

  // reserved
  REG_ADC_E01                  = 0x0115,
  REG_ADC_E03                  = 0x0116,
  REG_ADC_E02                  = 0x0117,

  // V = code/65536*3.0*10/3.32
  REG_ADC_GAUGE                = 0x0120,  // E04
  // V = code/65536*2.5
  REG_ADC_RF2_AMP_FEEDBACK     = 0x0121,  // E05
  // A = code/65535*3.0
  REG_ADC_RF_CURRENT           = 0x0122,  // E06
  // A = code/65536*2.5*1000/50/20
  REG_ADC_BASE_CURRENT         = 0x0123,
  // A = code/65536*2.5*1000/50/20
  REG_ADC_ARM_CURRENT          = 0x0124,
  // A = code/65536*2.5*1000/50/20
  REG_ADC_ROUGH_CURRENT        = 0x0125,
  // A = code/65536*2.5*1000/50/20
  REG_ADC_TURBO_CURRENT        = 0x0126,
  // V = code/65536*2.5
  REG_ADC_RF1_AMP_FEEDBACK     = 0x0127,  // dual-trap

  // V = code/65536*6.0-0.5
  REG_ADC_MS_SIGNAL            = 0x0130,

  // Debug registers
  REG_DEBUG_SDRAM_STATUS        = 0xFF00,
  REG_DEBUG_SCANING_STATUS      = 0xFF01,
  REG_DEBUG_SWIFT1_STATUS       = 0xFF02,
  REG_DEBUG_SWIFT2_STATUS       = 0xFF03,
  REG_DEBUG_SAMPLING_STATUS     = 0xFF04,
  REG_DEBUG_SAMPLING_TIME_LO    = 0xFF05,
  REG_DEBUG_SAMPLING_TIME_HI    = 0xFF06,
  REG_DEBUG_SAMPLING_SEGMENT_NO = 0xFF07,

  // Versions
  // firmware build version, value 100 means version .100
  REG_BUILD_VERSION             = 0xFFFC,
  // device model: 1-beta, 2-cell
  REG_MODEL                     = 0xFFFD, 
  // firmware version, value 100 means version 1.0.0
  REG_VERSION                   = 0xFFFE,
  // magic number, fixed value: 0xFACE
  REG_MAGIC_NUM                 = 0xFFFF,
  REG_INVALID                   = 0xFFFFFFFF
} REG_ADDR;
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

# 支持类

FpgaCommand是对FPGA USB消息接口的一个基本封装,它提供了对FPGA寄存器和内存的读写功能。FpgaCommand还提供了一个线程安全的、同步的执行接口Execute(),命令执行完成后,返回数据会被存储在data_received或reg_data中,供上层模块使用。

uml diagram

执行一个完整的FPGA操作(FpgaCommand)通常包括几个步骤:

  • 寄存器读写
    • 发送寄存器地址和操作模式(读或写)
    • 对于寄存器读操作,读取USB,获取2个字节
    • 对于寄存器写操作,发送2个字节的数据
  • 内存读写
    • 向内存地址寄存器写入内存地址(内存地址为32位,需要高、低内存地址2个寄存器)
    • 指定内存读写模式(向管道寄存器发送命令)
    • 对于内存读操作,读取最多2048个字节,如果超过2048个字节,需要重复上述步骤
    • 对于内存写操作,可以将数据一次性写入,完成后需要重置管道寄存器

为了更好的支持FpgaCommand,我们引入UsbCommand类,提供对USB读写的最基本封装。一个FpgaCommand由一组UsbCommand组成,底层USB收发无需理解FpgaCommand的逻辑,只需根据UsbCommand的类型发送或接收USB数据即可。

uml diagram

UsbManager是对usblib的封装,提供了执行FPGA Command的基本接口。UsbManager是一个单例,并运行在一个单独的线程里,FPGA命令的执行被串行化,因此避免了多线程USB读写可能引起的问题。
UsbManager在命令执行的过程中,会调用FpgaCommand的回调函数OnReadData()和OnComplete(),用来返回数据,或通知命令执行结束。

uml diagram