helper.go raw

   1  package gohex
   2  
   3  import (
   4  	"encoding/binary"
   5  	"encoding/hex"
   6  	"errors"
   7  	"fmt"
   8  	"io"
   9  	"strings"
  10  )
  11  
  12  func calcSum(bytes []byte) byte {
  13  	sum := 0
  14  	for _, b := range bytes {
  15  		sum += int(b)
  16  	}
  17  	sum %= 256
  18  	sum = 256 - sum
  19  	return byte(sum)
  20  }
  21  
  22  func checkSum(bytes []byte) error {
  23  	sum := calcSum(bytes[:len(bytes)-1])
  24  	last := bytes[len(bytes)-1]
  25  	if sum != last {
  26  		return errors.New("incorrect checksum (sum = " + fmt.Sprintf("%02X != %02X", sum, last) + ")")
  27  	}
  28  	return nil
  29  }
  30  
  31  func checkRecordSize(bytes []byte) error {
  32  	if (int(bytes[0]) + 5) != len(bytes) {
  33  		return errors.New("incorrect data length")
  34  	}
  35  	return nil
  36  }
  37  
  38  func checkEOF(bytes []byte) error {
  39  	if bytes[0] != 0 {
  40  		return errors.New("incorrect data length field in eof line")
  41  	}
  42  	if binary.BigEndian.Uint16(bytes[1:3]) != 0 {
  43  		return errors.New("incorrect address field in eof line")
  44  	}
  45  	return nil
  46  }
  47  
  48  func getExtendedAddress(bytes []byte) (adr uint32, err error) {
  49  	if bytes[0] != 2 {
  50  		return 0, errors.New("incorrect data length field in extended linear address line")
  51  	}
  52  	if binary.BigEndian.Uint16(bytes[1:3]) != 0 {
  53  		return 0, errors.New("incorrect address field in extended linear address line")
  54  	}
  55  	adr = uint32(binary.BigEndian.Uint16(bytes[4:6])) << (1 << bytes[3])
  56  	return adr, nil
  57  }
  58  
  59  func getDataLine(bytes []byte) (adr uint16, data []byte) {
  60  	size := bytes[0]
  61  	adr = binary.BigEndian.Uint16(bytes[1:3])
  62  	data = bytes[4 : size+4]
  63  	return adr, data
  64  }
  65  
  66  func getStartAddress(bytes []byte) (adr uint32, err error) {
  67  	if bytes[0] != 4 {
  68  		return 0, errors.New("incorrect data length field in start address line")
  69  	}
  70  	if binary.BigEndian.Uint16(bytes[1:3]) != 0 {
  71  		return 0, errors.New("incorrect address field in start address line")
  72  	}
  73  	adr = binary.BigEndian.Uint32(bytes[4:8])
  74  	return adr, nil
  75  }
  76  
  77  func makeDataLine(adr uint16, recordType byte, data []byte) []byte {
  78  	line := make([]byte, 5+len(data))
  79  	line[0] = byte(len(data))
  80  	binary.BigEndian.PutUint16(line[1:3], adr)
  81  	line[3] = recordType
  82  	copy(line[4:], data)
  83  	line[len(line)-1] = calcSum(line[:len(line)-1])
  84  	return line
  85  }
  86  
  87  func writeDataLine(writer io.Writer, lineAdr *uint32, byteAdr uint32, lineData *[]byte) error {
  88  	s := strings.ToUpper(hex.EncodeToString(makeDataLine(uint16(*lineAdr&0x0000FFFF), _DATA_RECORD, *lineData)))
  89  	_, err := fmt.Fprintf(writer, ":%s\n", s)
  90  	*lineAdr = byteAdr
  91  	*lineData = []byte{}
  92  	return err
  93  }
  94  
  95  func writeStartAddressLine(writer io.Writer, startAdr uint32) error {
  96  	a := make([]byte, 4)
  97  	binary.BigEndian.PutUint32(a, startAdr)
  98  	s := strings.ToUpper(hex.EncodeToString(makeDataLine(0, _START_RECORD, a)))
  99  	_, err := fmt.Fprintf(writer, ":%s\n", s)
 100  	return err
 101  }
 102  
 103  func writeExtendedAddressLine(writer io.Writer, extAdr uint32) {
 104  	a := make([]byte, 2)
 105  	binary.BigEndian.PutUint16(a, uint16(extAdr>>16))
 106  	s := strings.ToUpper(hex.EncodeToString(makeDataLine(0, _ADR_32_RECORD, a)))
 107  	fmt.Fprintf(writer, ":%s\n", s)
 108  }
 109  
 110  func writeEofLine(writer io.Writer) error {
 111  	s := strings.ToUpper(hex.EncodeToString(makeDataLine(0, _EOF_RECORD, []byte{})))
 112  	_, err := fmt.Fprintf(writer, ":%s\n", s)
 113  	return err
 114  }
 115