package sd import ( "encoding/binary" ) const ( _CMD_TIMEOUT = 100 _R1_IDLE_STATE = 1 << 0 _R1_ERASE_RESET = 1 << 1 _R1_ILLEGAL_COMMAND = 1 << 2 _R1_COM_CRC_ERROR = 1 << 3 _R1_ERASE_SEQUENCE_ERROR = 1 << 4 _R1_ADDRESS_ERROR = 1 << 5 _R1_PARAMETER_ERROR = 1 << 6 _DATA_RES_MASK = 0x1F _DATA_RES_ACCEPTED = 0x05 ) // response1 is the R1 response token returned by the card in SPI mode // after every command; a bitfield of error and idle-state flags. type response1 uint8 func (r response1) IsIdle() bool { return r&_R1_IDLE_STATE != 0 } func (r response1) IllegalCmdError() bool { return r&_R1_ILLEGAL_COMMAND != 0 } func (r response1) CRCError() bool { return r&_R1_COM_CRC_ERROR != 0 } func (r response1) EraseReset() bool { return r&_R1_ERASE_RESET != 0 } func (r response1) EraseSeqError() bool { return r&_R1_ERASE_SEQUENCE_ERROR != 0 } func (r response1) AddressError() bool { return r&_R1_ADDRESS_ERROR != 0 } func (r response1) ParamError() bool { return r&_R1_PARAMETER_ERROR != 0 } // response1Err wraps a non-zero response1 status as an error. type response1Err struct { context string status response1 } func (e response1Err) Error() string { if e.context != "" { return "sd:" + e.context + " " + e.status.Response() } return e.status.Response() } func (e response1) Response() string { b := make([]byte, 0, 8) return string(e.appendf(b)) } func (r response1) appendf(b []byte) []byte { b = append(b, '[') if r.IsIdle() { b = append(b, "idle,"...) } if r.EraseReset() { b = append(b, "erase-rst,"...) } if r.EraseSeqError() { b = append(b, "erase-seq,"...) } if r.CRCError() { b = append(b, "crc-err,"...) } if r.AddressError() { b = append(b, "addr-err,"...) } if r.ParamError() { b = append(b, "param-err,"...) } if r.IllegalCmdError() { b = append(b, "illegal-cmd,"...) } if len(b) > 1 { b = b[:len(b)-1] } b = append(b, ']') return b } func makeResponseError(status response1) error { return response1Err{ status: status, } } // Commands used to help generate this file: // - stringer -type=state -trimprefix=state -output=state_string.go // - stringer -type=status -trimprefix=status -output=status_string.go // Tokens that are sent by card during polling. // https://github.com/arduino-libraries/SD/blob/master/src/utility/SdInfo.h const ( tokSTART_BLOCK = 0xfe tokSTOP_TRAN = 0xfd tokWRITE_MULT = 0xfc ) // state is the card state machine state as encoded in the // CURRENT_STATE bits of the Card Status register (section 4.10.1). type state uint8 const ( stateIdle state = iota stateReady stateIdent stateStby stateTran stateData stateRcv statePrg stateDis ) // status represents the Card Status Register (R1), as per section 4.10.1. type status uint32 func (s status) state() state { return state(s >> 9 & 0xf) } // First status bits. const ( statusRsvd0 status = iota statusRsvd1 statusRsvd2 statusAuthSeqError statusRsvdSDIO statusAppCmd statusFXEvent statusRsvd7 statusReadyForData ) // Upper bound status bits. const ( statusEraseReset status = iota + 13 statusECCDisabled statusWPEraseSkip statusCSDOverwrite _ _ statusGenericError statusControllerError // internal card controller error statusECCFailed statusIllegalCommand statusComCRCError // CRC check of previous command failed statusLockUnlockFailed statusCardIsLocked // Signals that the card is locked by the host. statusWPViolation // Write protected violation statusEraseParamError // invalid write block selection for erase statusEraseSeqError // error in erase sequence statusBlockLenError // tx block length not allowed statusAddrError // misaligned address statusAddrOutOfRange // address out of range ) // r1 is the normal 48-bit response to a command in SD-bus mode, // as per section 4.9.1. It carries the 32-bit Card Status register. type r1 struct { data [48 / 8]byte // 48 bits of response. } func (r *r1) RawCopy() [6]byte { return r.data } func (r *r1) startbit() bool { return r.data[0]&(1<<7) != 0 } func (r *r1) txbit() bool { return r.data[0]&(1<<6) != 0 } func (r *r1) cmdidx() uint8 { return r.data[0] & 0b11_1111 } func (r *r1) cardstatus() status { return status(binary.BigEndian.Uint32(r.data[1:5])) } func (r *r1) CRC7() uint8 { return r.data[5] >> 1 } func (r *r1) endbit() bool { return r.data[5]&1 != 0 } func (r *r1) IsValid() bool { return r.endbit() && CRC7(r.data[:5]) == r.CRC7() } // r6 is the 48-bit Published RCA response, as per section 4.9.5. It carries // the card's new Relative Card Address and a subset of the Card Status bits. type r6 struct { data [48 / 8]byte } func (r *r6) RawCopy() [6]byte { return r.data } func (r *r6) startbit() bool { return r.data[0]&(1<<7) != 0 } func (r *r6) txbit() bool { return r.data[0]&(1<<6) != 0 } func (r *r6) cmdidx() uint8 { return r.data[0] & 0b11_1111 } func (r *r6) rca() uint16 { return binary.BigEndian.Uint16(r.data[1:3]) } func (r *r6) CardStatus() status { moveBit := func(b status, from, to uint) status { return (b & (1 << from)) >> from << to } // See 4.9.5 R6 (Published RCA response) of the SD Simplified Specification. s := status(binary.BigEndian.Uint16(r.data[1:5])) s = moveBit(s, 13, 19) s = moveBit(s, 14, 22) s = moveBit(s, 15, 23) return s } func (r *r6) CRC7() uint8 { return r.data[5] >> 1 } func (r *r6) endbit() bool { return r.data[5]&1 != 0 } func (r *r6) IsValid() bool { return r.endbit() && CRC7(r.data[:5]) == r.CRC7() } func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. var x [1]struct{} _ = x[statusRsvd0-0] _ = x[statusRsvd1-1] _ = x[statusRsvd2-2] _ = x[statusAuthSeqError-3] _ = x[statusRsvdSDIO-4] _ = x[statusAppCmd-5] _ = x[statusFXEvent-6] _ = x[statusRsvd7-7] _ = x[statusReadyForData-8] _ = x[statusEraseReset-13] _ = x[statusECCDisabled-14] _ = x[statusWPEraseSkip-15] _ = x[statusCSDOverwrite-16] _ = x[statusGenericError-19] _ = x[statusControllerError-20] _ = x[statusECCFailed-21] _ = x[statusIllegalCommand-22] _ = x[statusComCRCError-23] _ = x[statusLockUnlockFailed-24] _ = x[statusCardIsLocked-25] _ = x[statusWPViolation-26] _ = x[statusEraseParamError-27] _ = x[statusEraseSeqError-28] _ = x[statusBlockLenError-29] _ = x[statusAddrError-30] _ = x[statusAddrOutOfRange-31] } const ( _status_name_0 = "Rsvd0Rsvd1Rsvd2AuthSeqErrorRsvdSDIOAppCmdFXEventRsvd7ReadyForData" _status_name_1 = "EraseResetECCDisabledWPEraseSkipCSDOverwrite" _status_name_2 = "GenericErrorControllerErrorECCFailedIllegalCommandComCRCErrorLockUnlockFailedCardIsLockedWPViolationEraseParamErrorEraseSeqErrorBlockLenErrorAddrErrorAddrOutOfRange" ) var ( _status_index_0 = [...]uint8{0, 5, 10, 15, 27, 35, 41, 48, 53, 65} _status_index_1 = [...]uint8{0, 10, 21, 32, 44} _status_index_2 = [...]uint8{0, 12, 27, 36, 50, 61, 77, 89, 100, 115, 128, 141, 150, 164} ) func (i status) string() string { switch { case i <= 8: return _status_name_0[_status_index_0[i]:_status_index_0[i+1]] case 13 <= i && i <= 16: i -= 13 return _status_name_1[_status_index_1[i]:_status_index_1[i+1]] case 19 <= i && i <= 31: i -= 19 return _status_name_2[_status_index_2[i]:_status_index_2[i+1]] default: return "" } } func (s status) String() string { return string(s.appendf(nil, ',')) } func (s status) appendf(b []byte, delim byte) []byte { b = append(b, s.state().String()...) b = append(b, '[') if s == 0 { return append(b, ']') } for bit := 0; bit < 32; bit++ { if s&(1<= state(len(_state_index)-1) { return "" } return _state_name[_state_index[i]:_state_index[i+1]] }