实现应答器1023报文和830报文的编解码
This commit is contained in:
parent
6a0a47083f
commit
58ebf3842a
406
example/balise_1023_830/main.go
Normal file
406
example/balise_1023_830/main.go
Normal file
@ -0,0 +1,406 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
|
||||
"joylink.club/bj-rtsts-server/third_party/balise"
|
||||
)
|
||||
|
||||
type Transponder struct {
|
||||
// 应答器编号
|
||||
Code int
|
||||
// 应答器名称
|
||||
Name string
|
||||
// 应答器类型
|
||||
Type string
|
||||
// 校验码
|
||||
CheckSum string
|
||||
// 830报文
|
||||
Msg830 string
|
||||
// 1023报文
|
||||
Msg1023 string
|
||||
}
|
||||
|
||||
func main() {
|
||||
transponderMap := ReadTransponders()
|
||||
// v := transponderMap["FB121_BGZ"]
|
||||
// b1023 := convertToBalise1023(v.Msg1023)
|
||||
// replaced830 := replaceFirst10Bits(convertTo830(v.Msg830))
|
||||
// scrambled830 := scrambling(replaced830, b1023.S)
|
||||
// compare830(scrambled830, b1023.data830)
|
||||
|
||||
// count := 0
|
||||
for _, v := range transponderMap {
|
||||
// slog.Info("transponder", "name", v.Name, "code", v.Code, "checksum", v.CheckSum, "msg830", v.Msg830, "msg1023", v.Msg1023)
|
||||
byte104, err := balise.DecodeByteString(v.Msg1023)
|
||||
if err != nil {
|
||||
slog.Error("解码应答器数据失败", "name", v.Name, "code", v.Code, "err", err)
|
||||
continue
|
||||
}
|
||||
compare104Bytes(byte104, balise.ConvertByteStringToBytes(v.Msg830))
|
||||
// b1023 := convertToBalise1023(v.Msg1023)
|
||||
// source830 := convertTo830(v.Msg830)
|
||||
// // replaced830 := replaceFirst10Bits(source830)
|
||||
// // compare830(reverted830, source830)
|
||||
// descrambled830 := descrambling(b1023.data830, b1023.S)
|
||||
// reverted830 := revertFirst10Bits(descrambled830)
|
||||
// // // scrambled830 := scrambling(replaced830, b1023.S)
|
||||
// compare830(source830, reverted830)
|
||||
// count++
|
||||
// if count >= 10 {
|
||||
// break
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 比较830位数据
|
||||
func compare104Bytes(bytes104 []byte, compare104 []byte) {
|
||||
if len(bytes104) != 104 {
|
||||
panic("invalid length")
|
||||
}
|
||||
for i := 0; i < 104; i++ {
|
||||
fmt.Printf("%02x\n", bytes104[i])
|
||||
fmt.Printf("%02x\n\n", compare104[i])
|
||||
if bytes104[i] != compare104[i] {
|
||||
slog.Info("error", "index", i, "bytes104", fmt.Sprintf("%02x", bytes104[i]), "compare", fmt.Sprintf("%02x", compare104[i]))
|
||||
panic("104 bytes compare error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Balise1023 struct {
|
||||
bits []byte // 1023报文,1023bit
|
||||
data []byte // 数据位,913bit
|
||||
data830 []byte // 830位数据
|
||||
cb []byte // 控制位,3bit
|
||||
sb []byte // 加扰位,12bit
|
||||
S uint32 // 由加扰计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
||||
esb []byte // 额外修正位,10bit
|
||||
checkSum []byte // 校验位,85bit
|
||||
}
|
||||
|
||||
func newBalise1023(bits []byte) *Balise1023 {
|
||||
if len(bits) != 1023 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// for i := 0; i < 1023; i++ {
|
||||
// if i%10 == 0 {
|
||||
// println()
|
||||
// }
|
||||
// print(1022-i, ":", bits[i], ",")
|
||||
// }
|
||||
// println()
|
||||
balise1023 := &Balise1023{
|
||||
bits: bits,
|
||||
}
|
||||
balise1023.data = balise1023.getRange(1022, 110)
|
||||
if len(balise1023.data) != 913 {
|
||||
panic("invalid data length")
|
||||
}
|
||||
balise1023.data830 = convert913To830(balise1023.data)
|
||||
balise1023.check11To10()
|
||||
balise1023.cb = balise1023.getRange(109, 107)
|
||||
for i, v := range balise1023.cb {
|
||||
n := 109 - i
|
||||
name := "b" + strconv.Itoa(109-i)
|
||||
slog.Info("cb", name, v)
|
||||
if n == 109 && v == 1 {
|
||||
slog.Error("控制位cb错误:cb109应该为0,实际为1")
|
||||
} else if n == 108 && v == 1 {
|
||||
slog.Error("控制位cb错误:cb108应该为0,实际为1")
|
||||
} else if n == 107 && v == 0 {
|
||||
slog.Error("控制位cb错误:cb107应该为1,实际为0")
|
||||
}
|
||||
}
|
||||
balise1023.sb = balise1023.getRange(106, 95)
|
||||
balise1023.S = calculateS(balise1023.sb)
|
||||
balise1023.esb = balise1023.getRange(94, 85)
|
||||
balise1023.checkSum = balise1023.getRange(84, 0)
|
||||
slog.Info("msg length", "datalen", len(balise1023.data), "cblen", len(balise1023.cb), "sblen", len(balise1023.sb), "esblen", len(balise1023.esb), "checkSumlen", len(balise1023.checkSum))
|
||||
return balise1023
|
||||
}
|
||||
|
||||
func (b *Balise1023) getRange(start, end int) []byte {
|
||||
if start < 0 || end < 0 || start < end || start > 1022 {
|
||||
panic("invalid range")
|
||||
}
|
||||
return b.bits[1022-start : 1022-(end-1)]
|
||||
}
|
||||
|
||||
func (b *Balise1023) check11To10() {
|
||||
b913 := b.data
|
||||
compare := convert830To913(b.data830)
|
||||
for i := 0; i < 913; i++ {
|
||||
if b913[i] != compare[i] {
|
||||
slog.Info("error", "idx", i, "b913", b913[i], "compare", compare[i])
|
||||
panic("10 to 11 bit error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 转换字节字符串到bit数组,左边为最高有效位(MSB)
|
||||
func convertStringBytesToBits(msg string) []byte {
|
||||
length := len(msg)
|
||||
println("msg:", msg)
|
||||
bytes := make([]byte, length/2)
|
||||
for i := 0; i < length; i += 2 {
|
||||
v, err := strconv.ParseUint(msg[i:i+2], 16, 8)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
bytes[i/2] = byte(v)
|
||||
// slog.Info("i", "byteidx", i/2, "byte", fmt.Sprintf("%02x", v))
|
||||
}
|
||||
// 字节转换为bit数组
|
||||
bits := make([]byte, length/2*8)
|
||||
for i, bt := range bytes {
|
||||
for j := 0; j < 8; j++ {
|
||||
move := 7 - j
|
||||
idx := i*8 + j
|
||||
bits[idx] = (bt >> move) & 1
|
||||
}
|
||||
}
|
||||
return bits
|
||||
}
|
||||
|
||||
func convertTo830(msg string) []byte {
|
||||
length := len(msg)
|
||||
if length != 208 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// 字节转换为bit数组
|
||||
bits := convertStringBytesToBits(msg)
|
||||
bits830 := bits[0:830]
|
||||
return bits830
|
||||
}
|
||||
|
||||
func convertToBalise1023(msg string) *Balise1023 {
|
||||
length := len(msg)
|
||||
if length != 256 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// 字节转换为bit数组
|
||||
bits := convertStringBytesToBits(msg)
|
||||
bits1023 := bits[0:1023]
|
||||
slog.Info("bits length", "len", len(bits1023))
|
||||
return newBalise1023(bits1023)
|
||||
}
|
||||
|
||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组,除了第一个10位值,其余值求和,然后循环2的10次方次与其他值求和结果相加后模2的10次方,若结果和第一个10位值相同,则结束,此值即为原始的第一个10位值,将此值替换为第一个10位二进制数组,依然是左边为MSB
|
||||
func revertFirst10Bits(b []byte) []byte {
|
||||
if len(b) != 830 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组
|
||||
bits := make([]uint16, 83)
|
||||
for i := 0; i < 83; i++ {
|
||||
bits[i] = uint16(balise.ToValLeftMsb(b[i*10 : i*10+10]))
|
||||
// 打印输出
|
||||
for j := 0; j < 10; j++ {
|
||||
fmt.Printf("%01b", b[i*10+j])
|
||||
}
|
||||
print(" ")
|
||||
if i != 0 && i%10 == 9 {
|
||||
println()
|
||||
}
|
||||
}
|
||||
println()
|
||||
// 将除了第一个10位字整数求和
|
||||
sum := uint64(0)
|
||||
for i := 1; i < 83; i++ {
|
||||
sum += uint64(bits[i])
|
||||
}
|
||||
// 循环2的10次方次与其他值求和结果相加后模2的10次方
|
||||
for i := 0; i < 1024; i++ {
|
||||
test := sum + uint64(i)
|
||||
if test%1024 == uint64(bits[0]) {
|
||||
bits[0] = uint16(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
slog.Info("还原第一个10位值", "sum", sum, "bits[0]", bits[0], "bits[0]b", fmt.Sprintf("%010b", bits[0]))
|
||||
rbits := make([]byte, 830)
|
||||
// 将整个10位数组转换为二进制数组,依然是MSB
|
||||
u0bits := balise.ToBitsLeftMsb(int(bits[0]), 10)
|
||||
for i := 0; i < 10; i++ {
|
||||
rbits[i] = u0bits[i]
|
||||
}
|
||||
for i := 10; i < 830; i++ {
|
||||
rbits[i] = b[i]
|
||||
}
|
||||
// compare830(b, rbits)
|
||||
return rbits
|
||||
}
|
||||
|
||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组,然后求和后模2的10次方,得到的结果覆盖第一个10位值,然后将整个10位数组转换为二进制数组,依然是左边为MSB
|
||||
func replaceFirst10Bits(b []byte) []byte {
|
||||
if len(b) != 830 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组
|
||||
bits := make([]uint16, 83)
|
||||
for i := 0; i < 83; i++ {
|
||||
bits[i] = uint16(balise.ToValLeftMsb(b[i*10 : i*10+10]))
|
||||
// 打印输出
|
||||
for j := 0; j < 10; j++ {
|
||||
fmt.Printf("%01b", b[i*10+j])
|
||||
}
|
||||
print(" ")
|
||||
if i != 0 && i%10 == 9 {
|
||||
println()
|
||||
}
|
||||
}
|
||||
println()
|
||||
// 将每一个10位字整数求和后模2的10次方,得到的结果覆盖第一个10位值
|
||||
sum := uint64(0)
|
||||
for i := 0; i < 83; i++ {
|
||||
sum += uint64(bits[i])
|
||||
// fmt.Printf("i=%d, v10=%d, v10b=%010b\n", i, bits[i], bits[i])
|
||||
}
|
||||
bits[0] = uint16(sum % 1024)
|
||||
slog.Info("替换第一个10位值", "sum", sum, "bits[0]", bits[0], "bits[0]b", fmt.Sprintf("%010b", bits[0]))
|
||||
rbits := make([]byte, 830)
|
||||
// 将整个10位数组转换为二进制数组,依然是MSB
|
||||
u0bits := balise.ToBitsLeftMsb(int(bits[0]), 10)
|
||||
for i := 0; i < 10; i++ {
|
||||
rbits[i] = u0bits[i]
|
||||
}
|
||||
for i := 10; i < 830; i++ {
|
||||
rbits[i] = b[i]
|
||||
}
|
||||
// compare830(b, rbits)
|
||||
return rbits
|
||||
}
|
||||
|
||||
// 由加扰位计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
||||
func calculateS(sb []byte) uint32 {
|
||||
// 由加扰计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
||||
if len(sb) != 12 {
|
||||
panic("invalid length")
|
||||
}
|
||||
B := balise.ToValLeftMsb(sb)
|
||||
const A uint64 = 2801775573
|
||||
S := uint32((A * uint64(B)) % (1 << 32))
|
||||
slog.Info("由12位加扰位计算得到整数S", "B", B, "S", S, "Sb", fmt.Sprintf("%032b", S))
|
||||
return S
|
||||
}
|
||||
|
||||
// 由加扰计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
||||
// 1. 生成一个32位的线性反馈移位寄存器,其初始状态为S(左边为MSB)
|
||||
// 2. 系数h31,h30,h29,h27,h25和h0等于1(表示连接),所有其他系数都为0(表示不连接)
|
||||
// 3. 然后电路被时钟驱动m-1次,其中m是数据位的数量,同时输入dn的每一位dn(m-1),dn(m-2),...,dn(0),便生成加扰后的码位(在第一个时钟之前读取第一个输出out(m-1))
|
||||
// 4. 生成的加扰码位是dn的每一位与S的最高位的异或值
|
||||
// 5. 生成的加扰码位会根据系数进行异或反馈回S的最低位
|
||||
// 几种可能性:
|
||||
func scrambling(dn []byte, S uint32) []byte {
|
||||
if len(dn) != 830 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// const Polynomial = 0x000000AF
|
||||
out := make([]byte, len(dn))
|
||||
t := S // 寄存器初始值
|
||||
for i := 0; i < len(dn); i++ {
|
||||
msb := (t >> 31) & 1
|
||||
out[i] = (dn[i] ^ byte(msb)) & 1
|
||||
// fmt.Printf("i=%d, t=%032b, msb=%d, dn=%d, out=%d\n", i, t, msb, dn[i], out[i])
|
||||
xor := uint32(out[i])
|
||||
t = (xor << 30) ^ (xor << 29) ^ (xor << 28) ^ (xor << 26) ^ (xor << 24) ^ t
|
||||
t = (t << 1) | xor
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func descrambling(dn []byte, S uint32) []byte {
|
||||
if len(dn) != 830 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// const Polynomial = 0x000000AF
|
||||
out := make([]byte, len(dn))
|
||||
t := S // 寄存器初始值
|
||||
for i := 0; i < len(dn); i++ {
|
||||
msb := (t >> 31) & 1
|
||||
out[i] = (dn[i] ^ byte(msb)) & 1
|
||||
// fmt.Printf("i=%d, t=%032b, msb=%d, dn=%d, out=%d\n", i, t, msb, dn[i], out[i])
|
||||
xor := uint32(dn[i])
|
||||
t = (xor << 30) ^ (xor << 29) ^ (xor << 28) ^ (xor << 26) ^ (xor << 24) ^ t
|
||||
t = (t << 1) | xor
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// 将830位的二进制数组先以10位为一组分别转换为11位并组合
|
||||
func convert830To913(b830 []byte) []byte {
|
||||
if len(b830) != 830 {
|
||||
panic("invalid length")
|
||||
}
|
||||
b913 := make([]byte, 913)
|
||||
for i := 0; i < 83; i++ {
|
||||
b11 := balise.To11(b830[i*10 : i*10+10])
|
||||
for j := 0; j < 11; j++ {
|
||||
b913[i*11+j] = b11[j]
|
||||
}
|
||||
}
|
||||
return b913
|
||||
}
|
||||
|
||||
func convert913To830(b913 []byte) []byte {
|
||||
if len(b913) != 913 {
|
||||
panic("invalid length")
|
||||
}
|
||||
b830 := make([]byte, 830)
|
||||
for i := 0; i < 83; i++ {
|
||||
b10, err := balise.From11(b913[i*11 : i*11+11])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for j := 0; j < 10; j++ {
|
||||
b830[i*10+j] = b10[j]
|
||||
}
|
||||
}
|
||||
return b830
|
||||
}
|
||||
|
||||
func compare830(b830 []byte, compare830 []byte) {
|
||||
if len(b830) != 830 {
|
||||
panic("invalid length")
|
||||
}
|
||||
for i := 0; i < 83; i++ {
|
||||
for j := 0; j < 10; j++ {
|
||||
fmt.Printf("%01b", b830[i*10+j])
|
||||
}
|
||||
println()
|
||||
for j := 0; j < 10; j++ {
|
||||
fmt.Printf("%01b", compare830[i*10+j])
|
||||
}
|
||||
println()
|
||||
println()
|
||||
}
|
||||
for i := 0; i < 830; i++ {
|
||||
if b830[i] != compare830[i] {
|
||||
slog.Info("error", "index", i, "b830", b830[i], "compare", compare830[i])
|
||||
panic("830 bit compare error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 以11位为一组比较两个913位的报文
|
||||
func compare913(b913 []byte, b1023 *Balise1023) {
|
||||
if len(b913) != 913 {
|
||||
panic("invalid length")
|
||||
}
|
||||
compare := b1023.data
|
||||
for i := 0; i < 913; i += 11 {
|
||||
for j := 0; j < 11; j++ {
|
||||
print(b913[i+j])
|
||||
}
|
||||
println()
|
||||
for j := 0; j < 11; j++ {
|
||||
print(compare[i+j])
|
||||
}
|
||||
println()
|
||||
println()
|
||||
}
|
||||
}
|
156
example/balise_1023_830/read_excel.go
Normal file
156
example/balise_1023_830/read_excel.go
Normal file
@ -0,0 +1,156 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
fileName = "北岗子-应答器报文清单.xlsx"
|
||||
sheetName = "应答器报文清单"
|
||||
codeColumn = "应答器编号"
|
||||
nameColumn = "应答器名称"
|
||||
typeColumn = "类型"
|
||||
checkSumColumn = "校验码"
|
||||
msg830strColumn = "用户报文(830bits)"
|
||||
msg1023strColumn = "报文(1023bits)"
|
||||
)
|
||||
|
||||
var heads []string
|
||||
|
||||
func init() {
|
||||
initHeads()
|
||||
}
|
||||
|
||||
func initHeads() {
|
||||
heads = append(heads, codeColumn)
|
||||
heads = append(heads, nameColumn)
|
||||
heads = append(heads, typeColumn)
|
||||
heads = append(heads, checkSumColumn)
|
||||
heads = append(heads, msg830strColumn)
|
||||
heads = append(heads, msg1023strColumn)
|
||||
}
|
||||
|
||||
func buildHeadIndex(row []string) map[string]int {
|
||||
headIdx := make(map[string]int)
|
||||
for i, column := range row {
|
||||
column = HandleStringSpace(column)
|
||||
if column == codeColumn {
|
||||
headIdx[column] = i
|
||||
} else if column == nameColumn {
|
||||
headIdx[column] = i
|
||||
} else if column == typeColumn {
|
||||
headIdx[column] = i
|
||||
} else if column == checkSumColumn {
|
||||
headIdx[column] = i
|
||||
} else if column == msg830strColumn {
|
||||
headIdx[column] = i
|
||||
} else if column == msg1023strColumn {
|
||||
headIdx[column] = i
|
||||
}
|
||||
}
|
||||
// 检查headIndex是否完整
|
||||
if len(headIdx) <= 0 {
|
||||
return nil
|
||||
}
|
||||
checkHeadsIndex(headIdx, fileName, sheetName, heads)
|
||||
return headIdx
|
||||
}
|
||||
|
||||
func checkHeadsIndex(headIdx map[string]int, fileName, sheetName string, heads []string) {
|
||||
// 检查headIndex是否完整
|
||||
for _, v := range heads {
|
||||
if _, ok := headIdx[v]; !ok {
|
||||
slog.Error("表头缺失", "文件名", fileName, "SheetName", sheetName, "表头", v)
|
||||
panic("课时表头缺失")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ReadTransponders() map[string]Transponder {
|
||||
return readExcel(fileName, sheetName, readRows)
|
||||
}
|
||||
|
||||
func readExcel[T any](fileName, sheetName string, handle func(rows [][]string) map[string]T) map[string]T {
|
||||
f, err := excelize.OpenFile(fileName)
|
||||
if err != nil {
|
||||
slog.Error("打开表文件异常", "表名", fileName, "error", err)
|
||||
debug.PrintStack()
|
||||
panic("打开表文件异常")
|
||||
}
|
||||
defer func() {
|
||||
if err := f.Close(); err != nil {
|
||||
slog.Error("文件关闭异常", "error", err)
|
||||
}
|
||||
}()
|
||||
|
||||
rows, err := f.GetRows(sheetName)
|
||||
if err != nil {
|
||||
slog.Error("读取Sheet异常", "SheetName", sheetName, "error", err)
|
||||
panic(err)
|
||||
}
|
||||
// fmt.Println(rows)
|
||||
return handle(rows)
|
||||
}
|
||||
|
||||
func readRows(rows [][]string) map[string]Transponder {
|
||||
dataMap := make(map[string]Transponder)
|
||||
var headIdx map[string]int
|
||||
for _, row := range rows {
|
||||
if headIdx == nil {
|
||||
headIdx = buildHeadIndex(row)
|
||||
// if headIdx != nil {
|
||||
// slog.Info("读取到表头索引", "文件名", fileName, "表名", sheetName, "索引", headIdx)
|
||||
// }
|
||||
} else {
|
||||
rowSize := len(row)
|
||||
if rowSize <= 0 {
|
||||
continue
|
||||
}
|
||||
if rowSize <= headIdx[msg1023strColumn] {
|
||||
// slog.Info("非数据行", "row", row, "rowIndex", i)
|
||||
continue
|
||||
}
|
||||
codeStr := row[headIdx[codeColumn]]
|
||||
if codeStr == "" {
|
||||
continue
|
||||
}
|
||||
codeStr = HandleStringSpace(codeStr)
|
||||
code, err := strconv.ParseInt(codeStr, 10, 32)
|
||||
if err != nil {
|
||||
slog.Error("应答器编号错误", "编号", codeStr, "error", err)
|
||||
panic("应答器编号错误")
|
||||
}
|
||||
name := row[headIdx[nameColumn]]
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
name = HandleStringSpace(name)
|
||||
tp := row[headIdx[typeColumn]]
|
||||
checkSum := row[headIdx[checkSumColumn]]
|
||||
msg830 := row[headIdx[msg830strColumn]]
|
||||
msg1023 := row[headIdx[msg1023strColumn]]
|
||||
dataMap[name] = Transponder{
|
||||
Code: int(code),
|
||||
Name: name,
|
||||
Type: tp,
|
||||
CheckSum: checkSum,
|
||||
Msg830: msg830,
|
||||
Msg1023: msg1023,
|
||||
}
|
||||
}
|
||||
}
|
||||
slog.Info("读取结果", "文件名", fileName, "SheetName", sheetName, "总数", len(dataMap))
|
||||
// fmt.Println(dataMap)
|
||||
return dataMap
|
||||
}
|
||||
|
||||
func HandleStringSpace(s string) string {
|
||||
s = strings.ReplaceAll(s, " ", "")
|
||||
s = strings.ReplaceAll(s, "\n", "")
|
||||
return s
|
||||
}
|
32
example/ex1/main.go
Normal file
32
example/ex1/main.go
Normal file
@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import "log/slog"
|
||||
|
||||
func main() {
|
||||
a1 := calculateAvgAcc(136960.88, 24.41978)
|
||||
a2 := calculateAvgAcc(34874, 14.97515)
|
||||
slog.Info("根据位移和时间计算平均加速度", "通号平均加速度", a1, "动力学平均加速度", a2)
|
||||
avt1 := calculateAvgAccByV(6.94444, 24.41978)
|
||||
avt2 := calculateAvgAccByV(6.94444, 14.97515)
|
||||
slog.Info("根据速度和时间计算平均加速度", "通号平均加速度", avt1, "动力学平均加速度", avt2)
|
||||
s1 := calculateS(0.28437766432762146, 24.41978)
|
||||
s2 := calculateS(0.46373090147972107, 14.97515)
|
||||
slog.Info("根据加速度和时间计算位移", "通号最小位移", s1, "动力学最小位移", s2)
|
||||
slog.Info("实际位移", "通号实际位移差", 136960.88-s1, "动力学实际位移差", 34874-s2)
|
||||
}
|
||||
|
||||
// 根据位移和时间计算平均加速度(初始速度为0)
|
||||
// s单位为mm,t单位为s
|
||||
func calculateAvgAcc(s float32, t float32) float32 {
|
||||
return 2 * s / (t * t) / 1000
|
||||
}
|
||||
|
||||
// 根据速度和时间计算平均加速度(初始速度为0)
|
||||
func calculateAvgAccByV(v float32, t float32) float32 {
|
||||
return v / t
|
||||
}
|
||||
|
||||
// 根据加速度和时间计算位移(初始速度为0)
|
||||
func calculateS(a float32, t float32) float32 {
|
||||
return 0.5 * a * t * t * 1000
|
||||
}
|
56
example/lfsr/main.go
Normal file
56
example/lfsr/main.go
Normal file
@ -0,0 +1,56 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// fib_lfsr()
|
||||
galois_lfsr()
|
||||
}
|
||||
|
||||
/* taps: 16 14 13 11; feedback polynomial: x^16 + x^14 + x^13 + x^11 + 1 */
|
||||
func fib_lfsr() {
|
||||
startState := uint16(0xACE1)
|
||||
lfsr := startState
|
||||
var bit uint16
|
||||
period := uint64(0)
|
||||
for {
|
||||
slog.Info("fib_lfsr", "bit", fmt.Sprintf("%01b", lfsr&1), "lfsr", fmt.Sprintf("%016b", lfsr))
|
||||
bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1
|
||||
lfsr = (lfsr >> 1) | (bit << 15)
|
||||
period++
|
||||
if period == 15 {
|
||||
break
|
||||
}
|
||||
if lfsr == startState {
|
||||
break
|
||||
}
|
||||
}
|
||||
println(period)
|
||||
}
|
||||
|
||||
/* taps: 16 14 13 11; feedback polynomial: x^16 + x^14 + x^13 + x^11 + 1 */
|
||||
func galois_lfsr() {
|
||||
startState := uint16(0xACE1)
|
||||
lfsr := startState
|
||||
var bit uint16
|
||||
period := uint64(0)
|
||||
for {
|
||||
slog.Info("galois_lfsr", "bit", fmt.Sprintf("%01b", lfsr&1), "lfsr", fmt.Sprintf("%016b", lfsr))
|
||||
bit = lfsr & 1
|
||||
lfsr >>= 1
|
||||
if bit == 1 {
|
||||
lfsr ^= 0xB400
|
||||
}
|
||||
period++
|
||||
// if period == 15 {
|
||||
// break
|
||||
// }
|
||||
if lfsr == startState {
|
||||
break
|
||||
}
|
||||
}
|
||||
println(period)
|
||||
}
|
52
example/test/main.go
Normal file
52
example/test/main.go
Normal file
@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
func main() {
|
||||
d2, d1, d0 := encodeAcc(6.742071875)
|
||||
a := decode2Acc(d2, d1, d0)
|
||||
fmt.Println(a)
|
||||
}
|
||||
|
||||
const G = 9.80665
|
||||
|
||||
func encodeAcc(a float32) (d2, d1, d0 byte) {
|
||||
d2 = 0
|
||||
d1 = 0
|
||||
d0 = 0
|
||||
x := a / G
|
||||
v := uint32(0)
|
||||
for i := 17; i >= 0; i-- {
|
||||
t := float32(1.0 / math.Pow(2, float64(17-i)))
|
||||
if t > x {
|
||||
continue
|
||||
} else {
|
||||
v |= 1 << i
|
||||
x -= t
|
||||
}
|
||||
}
|
||||
fmt.Printf("%b, %b\n", v, v<<6)
|
||||
v <<= 6
|
||||
d0 = byte(v)
|
||||
d1 = byte(v >> 8)
|
||||
d2 = byte(v >> 16)
|
||||
fmt.Printf("%b, %b, %b\n", d2, d1, d0)
|
||||
return
|
||||
}
|
||||
|
||||
func decode2Acc(d2, d1, d0 byte) float32 {
|
||||
v := uint32(d2)<<10 | uint32(d1)<<2 | uint32(d0>>6)
|
||||
fmt.Printf("%b\n", v)
|
||||
x := float32(0)
|
||||
for i := 17; i >= 0; i-- {
|
||||
if v&(1<<i) != 0 {
|
||||
t := float32(1.0 / math.Pow(2, float64(17-i)))
|
||||
x += t
|
||||
}
|
||||
}
|
||||
fmt.Println(x)
|
||||
return x * G
|
||||
}
|
6
go.mod
6
go.mod
@ -46,10 +46,16 @@ require (
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.3 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/simonvetter/modbus v1.6.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect
|
||||
github.com/xuri/excelize/v2 v2.8.1 // indirect
|
||||
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect
|
||||
github.com/yohamta/donburi v1.3.9 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
|
13
go.sum
13
go.sum
@ -153,6 +153,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
|
||||
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
@ -164,6 +166,11 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
||||
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
|
||||
github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
@ -220,6 +227,12 @@ github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6
|
||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 h1:Chd9DkqERQQuHpXjR/HSV1jLZA6uaoiwwH3vSuF3IW0=
|
||||
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||
github.com/xuri/excelize/v2 v2.8.1 h1:pZLMEwK8ep+CLIUWpWmvW8IWE/yxqG0I1xcN6cVMGuQ=
|
||||
github.com/xuri/excelize/v2 v2.8.1/go.mod h1:oli1E4C3Pa5RXg1TBXn4ENCXDV5JUMlBluUhG7c+CEE=
|
||||
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 h1:qhbILQo1K3mphbwKh1vNm4oGezE1eF9fQWmNiIpSfI4=
|
||||
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||
github.com/yohamta/donburi v1.3.9 h1:sYAPaelSnxmoTGjgH9ZlYt4pUKrnwvAv4YGXxLZCK6E=
|
||||
github.com/yohamta/donburi v1.3.9/go.mod h1:5QkyraUjkzbMVTD2b8jaPFy1Uwjm/zdFN1c1lZGaezg=
|
||||
github.com/yousifnimah/Cryptx v1.0.1 h1:oZbB6CjvqOzkmoghsncb3/4sV2As8nqOJCjZPd08Xdw=
|
||||
|
@ -266,6 +266,7 @@ go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
|
||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||
golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk=
|
||||
golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c=
|
||||
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||
golang.org/x/mobile v0.0.0-20221012134814-c746ac228303 h1:K4fp1rDuJBz0FCPAWzIJwnzwNEM7S6yobdZzMrZ/Zws=
|
||||
golang.org/x/mobile v0.0.0-20221012134814-c746ac228303/go.mod h1:M32cGdzp91A8Ex9qQtyZinr19EYxzkFqDjW2oyHzTDQ=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 5f95106870ba0cc1e75766698c3dbee74c45b39f
|
||||
Subproject commit 8c6bfb2aeec50afc347b6276b9f8012072811b7e
|
@ -1 +1 @@
|
||||
Subproject commit b7bddc6226c642e35a5ff8bb69d7990390d67b8d
|
||||
Subproject commit 0c2a7613104f859e83091d1f6379e6e2fa1990ad
|
184
third_party/balise/codec.go
vendored
184
third_party/balise/codec.go
vendored
@ -1,6 +1,10 @@
|
||||
package balise
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// 应答器数据编解码器
|
||||
type Codec interface {
|
||||
@ -8,22 +12,172 @@ type Codec interface {
|
||||
|
||||
const (
|
||||
Bytes1023 = 128
|
||||
Bytes341 = 43
|
||||
)
|
||||
|
||||
// 解码应答器数据,1023/341位解码
|
||||
// bys - 128/43字节数据
|
||||
// return - 830/210位数据
|
||||
func Decode(bys []byte) ([]int, error) {
|
||||
size := len(bys)
|
||||
func Decode(byte128 []byte) ([]byte, error) {
|
||||
if len(byte128) != Bytes1023 {
|
||||
return nil, buildError("应答器报文长度错误, 期望长度为128字节")
|
||||
}
|
||||
bits1023 := convertTo1023Bits(byte128)
|
||||
// 检查控制位
|
||||
err := checkCb(bits1023)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 检查913位数据,并将913位数据转换为830位数据
|
||||
data913 := getRange(bits1023, 1022, 110)
|
||||
scrambled830, err := convert913To830(data913)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 根据加扰位计算得到加扰器初始值S
|
||||
S := calculateS(getRange(bits1023, 106, 95))
|
||||
// 解扰
|
||||
descrambled830 := descrambling(scrambled830, S)
|
||||
// 还原第一个10位值
|
||||
reverted830 := revertFirst10Bits(descrambled830)
|
||||
// 转换为左边为最高有效位(MSB)的字节数组
|
||||
byte104 := toBytes(reverted830)
|
||||
return byte104, nil
|
||||
}
|
||||
|
||||
if size == Bytes1023 {
|
||||
// 1023应答器解码
|
||||
return nil, nil
|
||||
} else if size == Bytes341 {
|
||||
// 341应答器解码
|
||||
return nil, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("不支持的应答器类型")
|
||||
// 解码应答器数据,1023/341位解码
|
||||
// msg - 128字节数据
|
||||
// return - 830/210位数据
|
||||
func DecodeByteString(msg string) ([]byte, error) {
|
||||
length := len(msg)
|
||||
if length != 256 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// 字节转换为字节数组
|
||||
slog.Debug("待解码的1023应答器报文", "msg", msg)
|
||||
bytes := ConvertByteStringToBytes(msg)
|
||||
return Decode(bytes)
|
||||
}
|
||||
|
||||
// 转换字节(16进制)字符串为字节数组
|
||||
func ConvertByteStringToBytes(msg string) []byte {
|
||||
length := len(msg)
|
||||
bytes := make([]byte, length/2)
|
||||
for i := 0; i < length; i += 2 {
|
||||
v, err := strconv.ParseUint(msg[i:i+2], 16, 8)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
bytes[i/2] = byte(v)
|
||||
// slog.Info("i", "byteidx", i/2, "byte", fmt.Sprintf("%02x", v))
|
||||
}
|
||||
return bytes
|
||||
}
|
||||
|
||||
// 将830位补末尾补1到832位,然后转换为左边为最高有效位(MSB)的字节数组
|
||||
func toBytes(reverted830 []byte) []byte {
|
||||
reverted830 = append(reverted830, 1, 1)
|
||||
byte104 := make([]byte, 104)
|
||||
for i := 0; i < 104; i++ {
|
||||
byte104[i] = byte(ToValLeftMsb(reverted830[i*8 : i*8+8]))
|
||||
}
|
||||
return byte104
|
||||
}
|
||||
|
||||
func buildError(msg string) error {
|
||||
return fmt.Errorf("应答器1023解码错误:%s", msg)
|
||||
}
|
||||
|
||||
// 检查控制位
|
||||
func checkCb(bits1023 []byte) error {
|
||||
cb := getRange(bits1023, 109, 107)
|
||||
for i, v := range cb {
|
||||
n := 109 - i
|
||||
name := "b" + strconv.Itoa(109-i)
|
||||
slog.Info("cb", name, v)
|
||||
if n == 109 && v == 1 {
|
||||
return buildError("控制位cb错误,b109应该为0,实际为1")
|
||||
} else if n == 108 && v == 1 {
|
||||
return buildError("控制位cb错误,b108应该为0,实际为1")
|
||||
} else if n == 107 && v == 0 {
|
||||
return buildError("控制位cb错误,b107应该为1,实际为0")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getRange(bits []byte, start, end int) []byte {
|
||||
if start < 0 || end < 0 || start < end || start > 1022 {
|
||||
panic("invalid range")
|
||||
}
|
||||
return bits[1022-start : 1022-(end-1)]
|
||||
}
|
||||
|
||||
// 转换128字节数据为1023位数据
|
||||
func convertTo1023Bits(byte128 []byte) []byte {
|
||||
if len(byte128) != 128 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// 字节转换为bit数组
|
||||
bits := make([]byte, 1024)
|
||||
for i, bt := range byte128 {
|
||||
for j := 0; j < 8; j++ {
|
||||
move := 7 - j
|
||||
idx := i*8 + j
|
||||
bits[idx] = (bt >> move) & 1
|
||||
}
|
||||
}
|
||||
bits1023 := bits[0:1023]
|
||||
return bits1023
|
||||
}
|
||||
|
||||
// 由加扰位计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
||||
func calculateS(sb []byte) uint32 {
|
||||
// 由加扰计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
||||
if len(sb) != 12 {
|
||||
panic("invalid length")
|
||||
}
|
||||
B := ToValLeftMsb(sb)
|
||||
const A uint64 = 2801775573
|
||||
S := uint32((A * uint64(B)) % (1 << 32))
|
||||
slog.Info("由12位加扰位计算得到整数S", "B", B, "S", S, "Sb", fmt.Sprintf("%032b", S))
|
||||
return S
|
||||
}
|
||||
|
||||
// 以11位为一组比较两个913位的报文
|
||||
func compare913(b913 []byte, compare []byte) {
|
||||
if len(b913) != 913 {
|
||||
panic("invalid length")
|
||||
}
|
||||
for i := 0; i < 913; i += 11 {
|
||||
for j := 0; j < 11; j++ {
|
||||
print(b913[i+j])
|
||||
}
|
||||
println()
|
||||
for j := 0; j < 11; j++ {
|
||||
print(compare[i+j])
|
||||
}
|
||||
println()
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
// 比较830位数据
|
||||
func compare830(b830 []byte, compare830 []byte) {
|
||||
if len(b830) != 830 {
|
||||
panic("invalid length")
|
||||
}
|
||||
for i := 0; i < 83; i++ {
|
||||
for j := 0; j < 10; j++ {
|
||||
fmt.Printf("%01b", b830[i*10+j])
|
||||
}
|
||||
println()
|
||||
for j := 0; j < 10; j++ {
|
||||
fmt.Printf("%01b", compare830[i*10+j])
|
||||
}
|
||||
println()
|
||||
println()
|
||||
}
|
||||
for i := 0; i < 830; i++ {
|
||||
if b830[i] != compare830[i] {
|
||||
slog.Info("error", "index", i, "b830", b830[i], "compare", compare830[i])
|
||||
panic("830 bit compare error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
113
third_party/balise/conv.go
vendored
113
third_party/balise/conv.go
vendored
@ -113,14 +113,83 @@ var ConvWords = []uint16{
|
||||
var convWordMap = make(map[uint16]int, 1024)
|
||||
|
||||
func init() {
|
||||
if len(ConvWords) != 1024 {
|
||||
panic(fmt.Errorf("ConvWords长度不是1024, len=%d", len(ConvWords)))
|
||||
}
|
||||
// 检查,前512个字的累加和为267528,所有1024个字的累加和为1048064
|
||||
sum1 := 0
|
||||
sum2 := 0
|
||||
for i := 0; i < 1024; i++ {
|
||||
if i < 512 {
|
||||
sum1 += int(ConvWords[i])
|
||||
}
|
||||
sum2 += int(ConvWords[i])
|
||||
}
|
||||
if sum1 != 267528 {
|
||||
panic(fmt.Errorf("前512个字的累加和不是267528, sum1=%d", sum1))
|
||||
}
|
||||
if sum2 != 1048064 {
|
||||
panic(fmt.Errorf("所有1024个字的累加和不是1048064, sum2=%d", sum2))
|
||||
}
|
||||
// 检查,后一个字比前一个字大
|
||||
for i := 1; i < 1024; i++ {
|
||||
if ConvWords[i] <= ConvWords[i-1] {
|
||||
panic(fmt.Errorf("第%d个字比第%d个字小, %04o <= %04o", i, i-1, ConvWords[i], ConvWords[i-1]))
|
||||
}
|
||||
}
|
||||
for i, v := range ConvWords {
|
||||
convWordMap[v] = i
|
||||
fmt.Printf("%04o: %d\n", v, i)
|
||||
// slog.Info("构建10位到11位转换置换字", "i", i, "v", v)
|
||||
}
|
||||
// 检查:翻转有效字的所有位能形成另一个有效字
|
||||
for _, v := range ConvWords {
|
||||
rv := revertBits(v)
|
||||
_, ok := convWordMap[rv]
|
||||
if !ok {
|
||||
panic(fmt.Errorf("构建10位到11位转换置换字失败, v=%04o, rv=%04o", v, rv))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 翻转11位bit数组
|
||||
func revertBits(word uint16) uint16 {
|
||||
bits11 := ToBitsLeftMsb(int(word), 11)
|
||||
revert := make([]byte, 11)
|
||||
for i := 0; i < 11; i++ {
|
||||
if bits11[i] == 1 {
|
||||
revert[i] = 0
|
||||
} else {
|
||||
revert[i] = 1
|
||||
}
|
||||
}
|
||||
rw := ToValLeftMsb(revert)
|
||||
// slog.Info("反转11位bit数组", "word", fmt.Sprintf("%04o", word), "bits11", bits11, "revert", revert, "revertWord", fmt.Sprintf("%04o", rw))
|
||||
return rw
|
||||
}
|
||||
|
||||
// bit数组转换为数字,左边为最高有效位
|
||||
// v - 0/1数组,数组的每个值都只能是0或1
|
||||
func ToVal(v []int) uint16 {
|
||||
func ToValLeftMsb(v []byte) uint16 {
|
||||
if len(v) > 15 {
|
||||
panic(fmt.Errorf("不支持15位以上"))
|
||||
}
|
||||
val := uint16(0)
|
||||
l := len(v)
|
||||
elems := make([]string, l)
|
||||
for i := 0; i < l; i++ {
|
||||
elems[i] = fmt.Sprintf("%d", v[i])
|
||||
if v[i] == 1 {
|
||||
val += (1 << (l - i - 1))
|
||||
}
|
||||
}
|
||||
// slog.Info("ToValLeftMsb", "len", l, "v", strings.Join(elems, ""), "val", fmt.Sprintf("%04o", val))
|
||||
return val
|
||||
}
|
||||
|
||||
// bit数组转换为数字,右边为最高有效位
|
||||
// v - 0/1数组,数组的每个值都只能是0或1
|
||||
func ToValRightMsb(v []byte) uint16 {
|
||||
if len(v) > 15 {
|
||||
panic(fmt.Errorf("不支持15位以上"))
|
||||
}
|
||||
@ -128,15 +197,15 @@ func ToVal(v []int) uint16 {
|
||||
l := len(v)
|
||||
for i := 0; i < l; i++ {
|
||||
if v[i] == 1 {
|
||||
val += (1 << (l - i - 1))
|
||||
val += (1 << i)
|
||||
}
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
// 数字转换为bit数组,左边为最高有效位
|
||||
func ToBits(val int, count int) []int {
|
||||
bs := make([]int, count)
|
||||
func ToBitsLeftMsb(val int, count int) []byte {
|
||||
bs := make([]byte, count)
|
||||
for i := 0; i < count; i++ {
|
||||
tmp := 1 << (count - 1 - i)
|
||||
if (val & (tmp)) == (tmp) {
|
||||
@ -148,26 +217,42 @@ func ToBits(val int, count int) []int {
|
||||
return bs
|
||||
}
|
||||
|
||||
// 11位字转换回10位字
|
||||
func From11(b11 []int) ([]int, error) {
|
||||
v11 := ToVal(b11)
|
||||
v10, ok := convWordMap[uint16(v11)]
|
||||
if ok {
|
||||
return ToBits(v10, 10), nil
|
||||
// 数字转换为bit数组,右边为最高有效位
|
||||
func ToBitsRightMsb(val int, count int) []byte {
|
||||
bs := make([]byte, count)
|
||||
for i := 0; i < count; i++ {
|
||||
tmp := 1 << i
|
||||
if (val & (tmp)) == (tmp) {
|
||||
bs[i] = 1
|
||||
} else {
|
||||
return nil, fmt.Errorf("错误的11位字")
|
||||
bs[i] = 0
|
||||
}
|
||||
}
|
||||
return bs
|
||||
}
|
||||
|
||||
// 11位字转换回10位字
|
||||
func From11(b11 []byte) ([]byte, error) {
|
||||
v11 := ToValLeftMsb(b11)
|
||||
v10, ok := convWordMap[v11]
|
||||
// slog.Info("11位字转换回10位字", "v11", fmt.Sprintf("%04o", v11), "v11b", fmt.Sprintf("%011b", v11), "v10", v10, "ok", ok, "v10bits", fmt.Sprintf("%010b", v10), "to10Bits", ToBitsLeftMsb(v10, 10))
|
||||
if ok {
|
||||
return ToBitsLeftMsb(v10, 10), nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("错误的11位字,word11=%04o", v11)
|
||||
}
|
||||
}
|
||||
|
||||
// 10位字转换为11位字
|
||||
func To11(b10 []int) []int {
|
||||
func To11(b10 []byte) []byte {
|
||||
if len(b10) != 10 {
|
||||
panic(fmt.Errorf("应答器编码10位字转换为11位字参数异常: 位数不是10, len=%d", len(b10)))
|
||||
}
|
||||
v10 := ToVal(b10)
|
||||
v10 := ToValLeftMsb(b10)
|
||||
if v10 > 1023 {
|
||||
panic(fmt.Errorf("应答器编码10位字转换为11位字参数异常: 10位字转为整数不能大于1023, v10=%d", v10))
|
||||
}
|
||||
v11 := ConvWords[v10]
|
||||
return ToBits(int(v11), 11)
|
||||
// slog.Info("10位字转换为11位字", "v10", v10, "v10b", fmt.Sprintf("%010b", v10), "v11", fmt.Sprintf("%04o", v11), "v11bits", fmt.Sprintf("%011b", v11), "to11Bits", ToBitsLeftMsb(int(v11), 11))
|
||||
return ToBitsLeftMsb(int(v11), 11)
|
||||
}
|
||||
|
2
third_party/balise/conv_test.go
vendored
2
third_party/balise/conv_test.go
vendored
@ -39,6 +39,6 @@ func TestConvList(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTo11(t *testing.T) {
|
||||
b10 := []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
|
||||
b10 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
|
||||
balise.To11(b10)
|
||||
}
|
||||
|
88
third_party/balise/decode.go
vendored
Normal file
88
third_party/balise/decode.go
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
package balise
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组,除了第一个10位值,其余值求和,然后循环2的10次方次与其他值求和结果相加后模2的10次方,若结果和第一个10位值相同,则结束,此值即为原始的第一个10位值,将此值替换为第一个10位二进制数组,依然是左边为MSB
|
||||
func revertFirst10Bits(b []byte) []byte {
|
||||
if len(b) != 830 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组
|
||||
w10s := make([]uint16, 83)
|
||||
for i := 0; i < 83; i++ {
|
||||
w10s[i] = uint16(ToValLeftMsb(b[i*10 : i*10+10]))
|
||||
// 打印输出
|
||||
for j := 0; j < 10; j++ {
|
||||
fmt.Printf("%01b", b[i*10+j])
|
||||
}
|
||||
print(" ")
|
||||
if i != 0 && i%10 == 9 {
|
||||
println()
|
||||
}
|
||||
}
|
||||
println()
|
||||
// 将除了第一个10位字整数求和
|
||||
sum := uint64(0)
|
||||
for i := 1; i < 83; i++ {
|
||||
sum += uint64(w10s[i])
|
||||
}
|
||||
// 循环2的10次方次与其他值求和结果相加后模2的10次方
|
||||
for i := 0; i < 1024; i++ {
|
||||
test := sum + uint64(i)
|
||||
if test%1024 == uint64(w10s[0]) {
|
||||
w10s[0] = uint16(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
slog.Info("还原第一个10位值", "sum", sum, "bits[0]", w10s[0], "bits[0]b", fmt.Sprintf("%010b", w10s[0]))
|
||||
bits := make([]byte, 830)
|
||||
// 将整个10位数组转换为二进制数组,依然是MSB
|
||||
u0bits := ToBitsLeftMsb(int(w10s[0]), 10)
|
||||
for i := 0; i < 10; i++ {
|
||||
bits[i] = u0bits[i]
|
||||
}
|
||||
for i := 10; i < 830; i++ {
|
||||
bits[i] = b[i]
|
||||
}
|
||||
return bits
|
||||
}
|
||||
|
||||
// 解扰,由加扰计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行解扰
|
||||
func descrambling(dn []byte, S uint32) []byte {
|
||||
if len(dn) != 830 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// const Polynomial = 0x000000AF
|
||||
out := make([]byte, len(dn))
|
||||
t := S // 寄存器初始值
|
||||
for i := 0; i < len(dn); i++ {
|
||||
msb := (t >> 31) & 1
|
||||
out[i] = (dn[i] ^ byte(msb)) & 1
|
||||
// fmt.Printf("i=%d, t=%032b, msb=%d, dn=%d, out=%d\n", i, t, msb, dn[i], out[i])
|
||||
xor := uint32(dn[i])
|
||||
t = (xor << 30) ^ (xor << 29) ^ (xor << 28) ^ (xor << 26) ^ (xor << 24) ^ t
|
||||
t = (t << 1) | xor
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// 转换913位数据为830位数据
|
||||
func convert913To830(b913 []byte) ([]byte, error) {
|
||||
if len(b913) != 913 {
|
||||
panic("invalid length")
|
||||
}
|
||||
b830 := make([]byte, 830)
|
||||
for i := 0; i < 83; i++ {
|
||||
b10, err := From11(b913[i*11 : i*11+11])
|
||||
if err != nil {
|
||||
return nil, buildError(err.Error())
|
||||
}
|
||||
for j := 0; j < 10; j++ {
|
||||
b830[i*10+j] = b10[j]
|
||||
}
|
||||
}
|
||||
return b830, nil
|
||||
}
|
86
third_party/balise/encode.go
vendored
Normal file
86
third_party/balise/encode.go
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
package balise
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组,然后求和后模2的10次方,得到的结果覆盖第一个10位值,然后将整个10位数组转换为二进制数组,依然是左边为MSB
|
||||
func replaceFirst10Bits(b []byte) []byte {
|
||||
if len(b) != 830 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组
|
||||
bits := make([]uint16, 83)
|
||||
for i := 0; i < 83; i++ {
|
||||
bits[i] = uint16(ToValLeftMsb(b[i*10 : i*10+10]))
|
||||
// 打印输出
|
||||
for j := 0; j < 10; j++ {
|
||||
fmt.Printf("%01b", b[i*10+j])
|
||||
}
|
||||
print(" ")
|
||||
if i != 0 && i%10 == 9 {
|
||||
println()
|
||||
}
|
||||
}
|
||||
println()
|
||||
// 将每一个10位字整数求和后模2的10次方,得到的结果覆盖第一个10位值
|
||||
sum := uint64(0)
|
||||
for i := 0; i < 83; i++ {
|
||||
sum += uint64(bits[i])
|
||||
// fmt.Printf("i=%d, v10=%d, v10b=%010b\n", i, bits[i], bits[i])
|
||||
}
|
||||
bits[0] = uint16(sum % 1024)
|
||||
slog.Info("替换第一个10位值", "sum", sum, "bits[0]", bits[0], "bits[0]b", fmt.Sprintf("%010b", bits[0]))
|
||||
rbits := make([]byte, 830)
|
||||
// 将整个10位数组转换为二进制数组,依然是MSB
|
||||
u0bits := ToBitsLeftMsb(int(bits[0]), 10)
|
||||
for i := 0; i < 10; i++ {
|
||||
rbits[i] = u0bits[i]
|
||||
}
|
||||
for i := 10; i < 830; i++ {
|
||||
rbits[i] = b[i]
|
||||
}
|
||||
// compare830(b, rbits)
|
||||
return rbits
|
||||
}
|
||||
|
||||
// 由加扰计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
||||
// 1. 生成一个32位的线性反馈移位寄存器,其初始状态为S(左边为MSB)
|
||||
// 2. 系数h31,h30,h29,h27,h25和h0等于1(表示连接),所有其他系数都为0(表示不连接)
|
||||
// 3. 然后电路被时钟驱动m-1次,其中m是数据位的数量,同时输入dn的每一位dn(m-1),dn(m-2),...,dn(0),便生成加扰后的码位(在第一个时钟之前读取第一个输出out(m-1))
|
||||
// 4. 生成的加扰码位是dn的每一位与S的最高位的异或值
|
||||
// 5. 生成的加扰码位会根据系数进行异或反馈回S的最低位
|
||||
// 几种可能性:
|
||||
func scrambling(dn []byte, S uint32) []byte {
|
||||
if len(dn) != 830 {
|
||||
panic("invalid length")
|
||||
}
|
||||
// const Polynomial = 0x000000AF
|
||||
out := make([]byte, len(dn))
|
||||
t := S // 寄存器初始值
|
||||
for i := 0; i < len(dn); i++ {
|
||||
msb := (t >> 31) & 1
|
||||
out[i] = (dn[i] ^ byte(msb)) & 1
|
||||
// fmt.Printf("i=%d, t=%032b, msb=%d, dn=%d, out=%d\n", i, t, msb, dn[i], out[i])
|
||||
xor := uint32(out[i])
|
||||
t = (xor << 30) ^ (xor << 29) ^ (xor << 28) ^ (xor << 26) ^ (xor << 24) ^ t
|
||||
t = (t << 1) | xor
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// 将830位的二进制数组先以10位为一组分别转换为11位并组合
|
||||
func convert830To913(b830 []byte) []byte {
|
||||
if len(b830) != 830 {
|
||||
panic("invalid length")
|
||||
}
|
||||
b913 := make([]byte, 913)
|
||||
for i := 0; i < 83; i++ {
|
||||
b11 := To11(b830[i*10 : i*10+10])
|
||||
for j := 0; j < 11; j++ {
|
||||
b913[i*11+j] = b11[j]
|
||||
}
|
||||
}
|
||||
return b913
|
||||
}
|
4
third_party/example/main.go
vendored
4
third_party/example/main.go
vendored
@ -46,13 +46,13 @@ func main() {
|
||||
// fmt.Println()
|
||||
// }
|
||||
// }
|
||||
v10 := balise.ToVal([]int{
|
||||
v10 := balise.ToValLeftMsb([]byte{
|
||||
1, 1, 1,
|
||||
1, 1, 1, 1,
|
||||
1, 1, 1, 1,
|
||||
1, 1, 1, 1})
|
||||
fmt.Println(v10)
|
||||
bs := balise.ToBits(1982, 11)
|
||||
bs := balise.ToBitsLeftMsb(1982, 11)
|
||||
fmt.Println(bs)
|
||||
// fmt.Printf("%o\n", balise.ConvWords[511])
|
||||
}
|
||||
|
BIN
北岗子-应答器报文清单.xlsx
Normal file
BIN
北岗子-应答器报文清单.xlsx
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user