44// Copyright mestrode <[email protected] >55// Original Source: "https://github.com/mestrode/Lin-Transceiver-Library"
66//
7- // Requires class Lin_Interface: https://github.com/mestrode/Lin-Interface-Library
8- //
9- // Tested with ESP32
7+ // Datasheet TJA1020: https://www.nxp.com/docs/en/data-sheet/TJA1020.pdf
108
119#include " TJA1020.hpp"
1210
1816 #include < Arduino.h>
1917#endif
2018
21- constexpr auto BAUD_DEFAULT = 19200 ;
22-
23- // -----------------------------------------------------------------------------
24- // constructor
25-
26- // / Provides HW UART via TJA1020 Chip
27- Lin_TJA1020::Lin_TJA1020 (const int _uart_nr, const uint32_t _baud, const int8_t _rxPin, const int8_t _txPin, const int8_t _nslpPin) :
19+ // / @brief Provides HAL for UART via TJA1020 Chip
20+ // / @param _uart_nr uart for LIN
21+ // / @param _baud max 20k. default 19.200 baud
22+ // / @param _rxPin GPIO
23+ // / @param _txPin GPIO
24+ // / @param _nslpPin GPIO
25+ // / @param _mode initial mode of statemachine within TJA
26+ Lin_TJA1020::Lin_TJA1020 (const int _uart_nr, const uint32_t _baud, const int8_t _rxPin, const int8_t _txPin, const int8_t _nslpPin, const Mode _mode) :
2827 HardwareSerial(_uart_nr),
28+ rxPin(_rxPin),
2929 txPin(_txPin),
3030 nslpPin(_nslpPin)
3131{
32- // use default baud rate, if not specified
33- // TODO: HardwareSerial::baudRate = _baud ? _baud : BAUD_DEFAULT;
34- HardwareSerial::setPins (_rxPin, _txPin);
35- }
32+ pinMode (nslpPin, OUTPUT);
33+ digitalWrite (nslpPin, LOW);
34+
35+ pinMode (rxPin, INPUT_PULLUP);
36+ pinMode (txPin, OUTPUT);
37+ HardwareSerial::setPins (rxPin, txPin);
3638
37- // -----------------------------------------------------------------------------
39+ HardwareSerial::updateBaudRate (_baud);
40+
41+ setMode (_mode);
42+ }
3843
3944// / does control sequences to switch from one to another operational mode of the chip
4045// / NormalSlope, LowSlope for writing operation;
@@ -49,112 +54,105 @@ void Lin_TJA1020::setMode(const Mode mode)
4954 return ;
5055 }
5156
52- pinMode (txPin, OUTPUT); // TX Signal to LIN Tranceiver
53- pinMode (nslpPin, OUTPUT); // /SLP Signal to LIN Tranceiver
54-
5557 // Statemachine des TJA1020 von [SLEEP] nach [NORMAL SLOPE MODE] ändern
56- switch (mode)
57- {
58- case Mode::NormalSlope:
58+ if (mode == Mode::NormalSlope) {
5959 if (_currentMode == Mode::LowSlope)
6060 {
6161 // no direct step from LowSlope to NormalSlope
62+ // TODO: no valid transission, go over SLEEP may cut power
6263 setMode (Mode::Sleep);
6364 }
6465
6566 // rising edge on /SLP while TXD = 1
6667 digitalWrite (txPin, HIGH);
67- delayMicroseconds (10 ); // ensure signal to settle
68+ delayMicroseconds (T_SETTLE);
6869
69- // create rising edge
7070 digitalWrite (nslpPin, LOW);
71- delayMicroseconds (15 ); // ensure t_gotosleep (min. 10us)
71+ delayMicroseconds (T_SETTLE);
7272 digitalWrite (nslpPin, HIGH);
73- delayMicroseconds (15 ); // ensure t_gotonorm (min. 10us)
73+ delayMicroseconds (T_GOTONORM);
7474
7575 // [Normal Slope Mode] reached
7676 _currentMode = Mode::NormalSlope;
77- break ;
77+ return ;
78+ }
7879
79- case Mode::LowSlope:
80+ if (mode == Mode::LowSlope) {
8081 if (_currentMode == Mode::NormalSlope)
8182 {
8283 // no direct step from NormalSlope to LowSlope
84+ // TODO: no valid transission, go over SLEEP may cut power
8385 setMode (Mode::Sleep);
8486 }
8587
8688 // rising edge on /SLP while TXD = 0
8789 digitalWrite (txPin, LOW);
88- delayMicroseconds (10 ); // ensure signal to settle
90+ delayMicroseconds (T_SETTLE);
8991
90- // create rising edge
9192 digitalWrite (nslpPin, LOW);
92- delayMicroseconds (15 ); // ensure t_gotosleep (min. 10us)
93+ delayMicroseconds (T_SETTLE);
9394 digitalWrite (nslpPin, HIGH);
94- delayMicroseconds (15 ); // ensure t_gotonorm (min. 10us)
95+ delayMicroseconds (T_GOTONORM);
9596
96- // release tx pin, to avoid occupation of Lin Bus
97- digitalWrite (txPin, HIGH );
97+ // release tx pin (active Low) , to avoid occupation of Lin Bus
98+ digitalWrite (txPin, LOW );
9899
99100 // [Low Slope Mode] reached
100101 _currentMode = Mode::LowSlope;
101- break ;
102+ return ;
103+ }
102104
103- default : // = Sleep
104- // no direct step from Standby to Sleep, but we don't know if we're in
105- // we're going over _writingSlope
106- setMode (Mode::NormalSlope);
105+ // default: mode == Mode::Sleep or Mode::Standby
107106
108- // rising edge on /SLP while TXD = 1
109- digitalWrite (txPin, HIGH);
110- delayMicroseconds (10 ); // ensure signal to settle
107+ // no direct step from Standby to Sleep
108+ if (_currentMode == Mode::Standby) {
109+ // we're going over LowSlope
110+ setMode (Mode::LowSlope);
111+ }
111112
112- // create falling edge
113- digitalWrite (nslpPin, HIGH);
114- delayMicroseconds (15 ); // ensure t_gotosleep (min. 10us)
115- digitalWrite (nslpPin, LOW);
116- delayMicroseconds (15 ); // ensure t_gotonorm (min. 10us)
117- // INH will be shut down by constant low, chip will go into sleep mode
113+ // rising edge on /SLP while TXD = 1
114+ digitalWrite (txPin, HIGH);
115+ delayMicroseconds (T_SETTLE);
118116
119- // ensure pin level while sleeping
120- #ifdef ESP32
121- pinMode (txPin, INPUT_PULLDOWN); // ensure Low level while in sleep mode (since TJA1020 has internally a fixed pulldown)
122- pinMode (nslpPin, INPUT_PULLDOWN); // ensure Low level while in sleep mode
123- #else
124- pinMode (txPin, INPUT); // ensure Low level while in sleep mode (since TJA1020 has internally a fixed pulldown)
125- pinMode (nslpPin, INPUT); // ensure Low level while in sleep mode
126- #endif
117+ digitalWrite (nslpPin, HIGH);
118+ delayMicroseconds (T_SETTLE);
127119
128- // [Sleep] reached
129- _currentMode = Mode::Sleep;
130- break ;
131- }
132- } // void Lin_TJA1020::setMode(TJA1020_Mode newMode)
120+ digitalWrite (nslpPin, LOW);
121+ // ! avoid another sleep, cause chip will go into sleep mode soon
122+ // ! --> INH will float = this may cause power cut off
123+ // ! delayMicroseconds(T_GOTOSLEEP);
124+
125+ // ! since TJA1020 has internally a fixed pulldown ensure Low level while in sleep mode
126+ // ! digitalWrite(txPin, LOW);
127+
128+ _currentMode = Mode::Sleep;
129+ }
133130
134131Lin_TJA1020::Mode Lin_TJA1020::getMode ()
135132{
136- if (_currentMode == Mode::Sleep) {
133+ return _currentMode;
134+ }
137135
138- // test MCU PullUp against TJA Pulldown
139- pinMode (txPin, INPUT);
140- delayMicroseconds (1 ); // settle time
141- bool hasWeakPullDn = !digitalRead (txPin);
136+ // / @brief returns Wakeup Reason, this only possible after wakeup, before setMode() (standby mode will be detected)
137+ // / @return wake-up reason
138+ Lin_TJA1020::WakeUpSource Lin_TJA1020::getWakeupReason ()
139+ {
140+ // only in standby mode TXD pull-down can be tested
142141
143- pinMode (txPin, INPUT_PULLUP);
144- delayMicroseconds (1 ); // settle time
145- bool hasStrongPullDn = !digitalRead (txPin);
142+ // in Standby mode: /SLP must be low AND RXD must be low
143+ // --> equal to: /SLP is high OR RXD is high
144+ if (digitalRead (nslpPin) || digitalRead (rxPin)) {
145+ return WakeUpSource::unknown;
146+ }
147+ _currentMode == Mode::Standby;
146148
147- // revert setting
148- pinMode (txPin, INPUT);
149+ // test MCU pullup vs. TJA (weak) pull-down
150+ pinMode (txPin, INPUT_PULLUP);
151+ delayMicroseconds (T_SETTLE);
152+ bool hasTxWeakPullDn = digitalRead (txPin);
153+ // revert setting
154+ pinMode (txPin, OUTPUT);
149155
150- if (hasWeakPullDn && !hasStrongPullDn)
151- {
152- // TXD has weak pull-down on remote wake-up
153- _currentMode = Mode::StandbyWakeupRemote;
154- } else {
155- // TXD has strong pull-down on local wake-up (caused by /WAKE pin)
156- _currentMode = Mode::StandbyWakeupLocal;
157- }
158- }
159- return _currentMode;
156+ // TXD has weak pull-down on remote wake-up
157+ return hasTxWeakPullDn ? WakeUpSource::remote: WakeUpSource::local;
160158}
0 commit comments