Electric Locomotive control system. Touch screen driver control, includes regenerative braking, drives 4 brushless motors, displays speed MPH, system volts and power
Dependencies: BSP_DISCO_F746NG FastPWM LCD_DISCO_F746NG SD_DISCO_F746NG TS_DISCO_F746NG mbed
sd_card.cpp@1:8ef34deb5177, 2017-11-13 (annotated)
- Committer:
- JonFreeman
- Date:
- Mon Nov 13 09:53:00 2017 +0000
- Revision:
- 1:8ef34deb5177
Brushless Motor electric locomotive congtrol system; Drives 4 motors using touch-screen control.; Displays speed MPH, system volts and power
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
JonFreeman | 1:8ef34deb5177 | 1 | #include "mbed.h" |
JonFreeman | 1:8ef34deb5177 | 2 | #include "Electric_Loco.h" |
JonFreeman | 1:8ef34deb5177 | 3 | #include "SD_DISCO_F746NG.h" |
JonFreeman | 1:8ef34deb5177 | 4 | /* |
JonFreeman | 1:8ef34deb5177 | 5 | SD card used only to keep log of total distance travelled. |
JonFreeman | 1:8ef34deb5177 | 6 | Odometer is trivial. |
JonFreeman | 1:8ef34deb5177 | 7 | This file treats SD card as random access memory. |
JonFreeman | 1:8ef34deb5177 | 8 | A better implementation would use library functions for FAT file system etc. |
JonFreeman | 1:8ef34deb5177 | 9 | |
JonFreeman | 1:8ef34deb5177 | 10 | May revisit this. |
JonFreeman | 1:8ef34deb5177 | 11 | |
JonFreeman | 1:8ef34deb5177 | 12 | */ |
JonFreeman | 1:8ef34deb5177 | 13 | SD_DISCO_F746NG sd; |
JonFreeman | 1:8ef34deb5177 | 14 | extern Serial pc; |
JonFreeman | 1:8ef34deb5177 | 15 | extern uint32_t historic_distance; |
JonFreeman | 1:8ef34deb5177 | 16 | extern uint32_t get_pulse_total () ; |
JonFreeman | 1:8ef34deb5177 | 17 | |
JonFreeman | 1:8ef34deb5177 | 18 | static const int |
JonFreeman | 1:8ef34deb5177 | 19 | SD_BLOCKSIZE = 512; /* SD card data Block Size in Bytes */ |
JonFreeman | 1:8ef34deb5177 | 20 | // Assume SD card size is 4Gbyte, might be 8 Gbyte |
JonFreeman | 1:8ef34deb5177 | 21 | // Then can use 8388608 blocks (8 * 1024 * 1024) |
JonFreeman | 1:8ef34deb5177 | 22 | |
JonFreeman | 1:8ef34deb5177 | 23 | uint64_t SD_blockptr = 0; |
JonFreeman | 1:8ef34deb5177 | 24 | uint32_t SDBuffer[(SD_BLOCKSIZE >> 2)]; // = space for (512 / 4) uint32_t |
JonFreeman | 1:8ef34deb5177 | 25 | uint8_t SD_state = SD_OK, sd_jf = 0; |
JonFreeman | 1:8ef34deb5177 | 26 | |
JonFreeman | 1:8ef34deb5177 | 27 | static const uint64_t GIGAB = 1024 * 1024 * 1024; |
JonFreeman | 1:8ef34deb5177 | 28 | //static const uint64_t SDBLOCKS = (GIGAB / SD_BLOCKSIZE) * 4; // software drives SD up to 4Gbyte only - 8 M block |
JonFreeman | 1:8ef34deb5177 | 29 | static const uint64_t SDBLOCKS = (GIGAB / SD_BLOCKSIZE) * 2; // software drives SD up to 4Gbyte only - 8 M block |
JonFreeman | 1:8ef34deb5177 | 30 | // If data logger takes 2 minutes to fill 1 block, a 4G card takes 32 years run-time to fill |
JonFreeman | 1:8ef34deb5177 | 31 | // If system generates approx 320 pulses per metre travelled, max distance recordable in uint32_t is 65536 * 65536 / 320 = 13421.772 km |
JonFreeman | 1:8ef34deb5177 | 32 | bool sd_error () { // Test and Clear error code sd_jf, return true if any error bits set, false on 0 |
JonFreeman | 1:8ef34deb5177 | 33 | bool retval = false; |
JonFreeman | 1:8ef34deb5177 | 34 | if (sd_jf != 0) { |
JonFreeman | 1:8ef34deb5177 | 35 | retval = true; |
JonFreeman | 1:8ef34deb5177 | 36 | sd_jf = 0; |
JonFreeman | 1:8ef34deb5177 | 37 | } |
JonFreeman | 1:8ef34deb5177 | 38 | return retval; |
JonFreeman | 1:8ef34deb5177 | 39 | } |
JonFreeman | 1:8ef34deb5177 | 40 | |
JonFreeman | 1:8ef34deb5177 | 41 | bool check_SD_block_clear (uint32_t block) { |
JonFreeman | 1:8ef34deb5177 | 42 | uint32_t b[(SD_BLOCKSIZE >> 2)]; |
JonFreeman | 1:8ef34deb5177 | 43 | SD_state = sd.ReadBlocks(b, (uint64_t)(SD_BLOCKSIZE * block), SD_BLOCKSIZE, 1); |
JonFreeman | 1:8ef34deb5177 | 44 | if(SD_state != SD_OK) { |
JonFreeman | 1:8ef34deb5177 | 45 | sd_jf = 1; |
JonFreeman | 1:8ef34deb5177 | 46 | pc.printf ("Failed, not SD_OK, erasing block %d\r\n", block); |
JonFreeman | 1:8ef34deb5177 | 47 | return false; |
JonFreeman | 1:8ef34deb5177 | 48 | } |
JonFreeman | 1:8ef34deb5177 | 49 | for (int i = 0; i < (SD_BLOCKSIZE >> 2); i++) |
JonFreeman | 1:8ef34deb5177 | 50 | if (b[i] != 0) |
JonFreeman | 1:8ef34deb5177 | 51 | return false; |
JonFreeman | 1:8ef34deb5177 | 52 | return true; |
JonFreeman | 1:8ef34deb5177 | 53 | } |
JonFreeman | 1:8ef34deb5177 | 54 | |
JonFreeman | 1:8ef34deb5177 | 55 | bool read_SD_state () { |
JonFreeman | 1:8ef34deb5177 | 56 | if (SD_state == SD_OK) |
JonFreeman | 1:8ef34deb5177 | 57 | return true; |
JonFreeman | 1:8ef34deb5177 | 58 | return false; |
JonFreeman | 1:8ef34deb5177 | 59 | } |
JonFreeman | 1:8ef34deb5177 | 60 | /*bool erase_block (uint32_t block2erase) { |
JonFreeman | 1:8ef34deb5177 | 61 | uint64_t addr = SD_BLOCKSIZE * (uint64_t)block2erase; |
JonFreeman | 1:8ef34deb5177 | 62 | SD_state = sd.Erase(addr, addr + SD_BLOCKSIZE); |
JonFreeman | 1:8ef34deb5177 | 63 | if (SD_state != SD_OK) { |
JonFreeman | 1:8ef34deb5177 | 64 | sd_jf = 1; // Assert error flag |
JonFreeman | 1:8ef34deb5177 | 65 | pc.printf ("Failed, not SD_OK, erasing block %d\r\n", block2erase); |
JonFreeman | 1:8ef34deb5177 | 66 | return false; |
JonFreeman | 1:8ef34deb5177 | 67 | } |
JonFreeman | 1:8ef34deb5177 | 68 | return check_SD_block_clear (block2erase); |
JonFreeman | 1:8ef34deb5177 | 69 | }*/ |
JonFreeman | 1:8ef34deb5177 | 70 | |
JonFreeman | 1:8ef34deb5177 | 71 | bool SD_find_next_clear_block (uint64_t * blok) { // Successive approximation algorithm to quickly find next vacant SD card 512 byte block |
JonFreeman | 1:8ef34deb5177 | 72 | uint64_t toaddsub = SDBLOCKS / 2, stab = SDBLOCKS - 1; |
JonFreeman | 1:8ef34deb5177 | 73 | pc.printf ("At SD_find_next_clear_block \r\n"); |
JonFreeman | 1:8ef34deb5177 | 74 | while (toaddsub) { |
JonFreeman | 1:8ef34deb5177 | 75 | pc.printf ("stab = %lld, toadsub = %lld\r\n", stab, toaddsub); // lld for long long int |
JonFreeman | 1:8ef34deb5177 | 76 | bool clear_block = true; |
JonFreeman | 1:8ef34deb5177 | 77 | SD_state = sd.ReadBlocks(SDBuffer, SD_BLOCKSIZE * stab, SD_BLOCKSIZE, 1); |
JonFreeman | 1:8ef34deb5177 | 78 | if(SD_state != SD_OK) { |
JonFreeman | 1:8ef34deb5177 | 79 | sd_jf = 1; |
JonFreeman | 1:8ef34deb5177 | 80 | pc.printf ("SD error in SD_find_next_clear_block, returning -1\r\n"); |
JonFreeman | 1:8ef34deb5177 | 81 | return false; |
JonFreeman | 1:8ef34deb5177 | 82 | } |
JonFreeman | 1:8ef34deb5177 | 83 | for (int i = 0; i < (SD_BLOCKSIZE >> 2); i++) { |
JonFreeman | 1:8ef34deb5177 | 84 | if (SDBuffer[i] != 0) { |
JonFreeman | 1:8ef34deb5177 | 85 | clear_block = false; |
JonFreeman | 1:8ef34deb5177 | 86 | pc.printf ("Buff at %d contains %x\r\n", i, SDBuffer[i]); |
JonFreeman | 1:8ef34deb5177 | 87 | i = SD_BLOCKSIZE; // to exit loop |
JonFreeman | 1:8ef34deb5177 | 88 | } |
JonFreeman | 1:8ef34deb5177 | 89 | } |
JonFreeman | 1:8ef34deb5177 | 90 | if (clear_block) |
JonFreeman | 1:8ef34deb5177 | 91 | stab -= toaddsub; |
JonFreeman | 1:8ef34deb5177 | 92 | else |
JonFreeman | 1:8ef34deb5177 | 93 | stab += toaddsub; |
JonFreeman | 1:8ef34deb5177 | 94 | toaddsub >>= 1; |
JonFreeman | 1:8ef34deb5177 | 95 | } |
JonFreeman | 1:8ef34deb5177 | 96 | if (!check_SD_block_clear(stab)) |
JonFreeman | 1:8ef34deb5177 | 97 | stab++; |
JonFreeman | 1:8ef34deb5177 | 98 | if (sd_error()) { // sd_error() tests and clears error bits |
JonFreeman | 1:8ef34deb5177 | 99 | pc.printf ("check_SD_block_clear(%ld)returned ERROR in SD_find_next_clear_block\r\n", stab); |
JonFreeman | 1:8ef34deb5177 | 100 | sd_jf = 1; // reassert error flag |
JonFreeman | 1:8ef34deb5177 | 101 | return false; |
JonFreeman | 1:8ef34deb5177 | 102 | } |
JonFreeman | 1:8ef34deb5177 | 103 | pc.printf ("Completed find_next, stab = %d\r\n", stab); |
JonFreeman | 1:8ef34deb5177 | 104 | *blok = stab; // block number of next free block |
JonFreeman | 1:8ef34deb5177 | 105 | return true; |
JonFreeman | 1:8ef34deb5177 | 106 | } |
JonFreeman | 1:8ef34deb5177 | 107 | |
JonFreeman | 1:8ef34deb5177 | 108 | bool SD_card_erase_all (void) { // assumes sd card is 4 Gbyte, erases 4 Gbyte. Called from CLI |
JonFreeman | 1:8ef34deb5177 | 109 | uint64_t EndAddr = GIGAB * 4, |
JonFreeman | 1:8ef34deb5177 | 110 | StartAddr = 0LL; |
JonFreeman | 1:8ef34deb5177 | 111 | sd_jf = 0; |
JonFreeman | 1:8ef34deb5177 | 112 | pc.printf ("Erasing SD card ... "); |
JonFreeman | 1:8ef34deb5177 | 113 | // uint8_t Erase(uint64_t StartAddr, uint64_t EndAddr); |
JonFreeman | 1:8ef34deb5177 | 114 | SD_state = sd.Erase(StartAddr, EndAddr); |
JonFreeman | 1:8ef34deb5177 | 115 | if (SD_state != SD_OK) { |
JonFreeman | 1:8ef34deb5177 | 116 | pc.printf ("SD_card_erase_all FAILED\r\n"); |
JonFreeman | 1:8ef34deb5177 | 117 | sd_jf = 1; |
JonFreeman | 1:8ef34deb5177 | 118 | return false; |
JonFreeman | 1:8ef34deb5177 | 119 | } |
JonFreeman | 1:8ef34deb5177 | 120 | pc.printf ("no error detected\r\n"); |
JonFreeman | 1:8ef34deb5177 | 121 | return true; |
JonFreeman | 1:8ef34deb5177 | 122 | } |
JonFreeman | 1:8ef34deb5177 | 123 | |
JonFreeman | 1:8ef34deb5177 | 124 | |
JonFreeman | 1:8ef34deb5177 | 125 | bool mainSDtest() |
JonFreeman | 1:8ef34deb5177 | 126 | { |
JonFreeman | 1:8ef34deb5177 | 127 | SD_state = sd.Init(); |
JonFreeman | 1:8ef34deb5177 | 128 | if(SD_state != SD_OK) { |
JonFreeman | 1:8ef34deb5177 | 129 | pc.printf ("sd.Init set SD_state to %0x\r\n", SD_state); |
JonFreeman | 1:8ef34deb5177 | 130 | if(SD_state == MSD_ERROR_SD_NOT_PRESENT) { |
JonFreeman | 1:8ef34deb5177 | 131 | pc.printf("SD shall be inserted before running test\r\n"); |
JonFreeman | 1:8ef34deb5177 | 132 | } else { |
JonFreeman | 1:8ef34deb5177 | 133 | pc.printf("SD Initialization : FAIL.\r\n"); |
JonFreeman | 1:8ef34deb5177 | 134 | } |
JonFreeman | 1:8ef34deb5177 | 135 | pc.printf("SD Test Aborted.\r\n"); |
JonFreeman | 1:8ef34deb5177 | 136 | return false; |
JonFreeman | 1:8ef34deb5177 | 137 | } |
JonFreeman | 1:8ef34deb5177 | 138 | // else { // SD_state is SD_OK |
JonFreeman | 1:8ef34deb5177 | 139 | pc.printf("SD Initialization : OK.\r\n"); |
JonFreeman | 1:8ef34deb5177 | 140 | |
JonFreeman | 1:8ef34deb5177 | 141 | |
JonFreeman | 1:8ef34deb5177 | 142 | |
JonFreeman | 1:8ef34deb5177 | 143 | // SD_card_erase_all(); |
JonFreeman | 1:8ef34deb5177 | 144 | // if (sd_error()) |
JonFreeman | 1:8ef34deb5177 | 145 | // pc.printf ("SD_card_erase_all() reports ERROR"); |
JonFreeman | 1:8ef34deb5177 | 146 | |
JonFreeman | 1:8ef34deb5177 | 147 | |
JonFreeman | 1:8ef34deb5177 | 148 | |
JonFreeman | 1:8ef34deb5177 | 149 | SD_find_next_clear_block(& SD_blockptr); |
JonFreeman | 1:8ef34deb5177 | 150 | pc.printf ("SD_find_next_clear_block returned %lld\r\n\n\n", SD_blockptr); |
JonFreeman | 1:8ef34deb5177 | 151 | if (sd_error()) { |
JonFreeman | 1:8ef34deb5177 | 152 | pc.printf ("***** ERROR returned from SD_find_next_clear_block ***** SD ops aborted\r\n"); |
JonFreeman | 1:8ef34deb5177 | 153 | return false; |
JonFreeman | 1:8ef34deb5177 | 154 | } |
JonFreeman | 1:8ef34deb5177 | 155 | pc.printf("SD_find_next_clear_block() returned %ld\r\n", SD_blockptr); |
JonFreeman | 1:8ef34deb5177 | 156 | if (SD_blockptr < 1) { |
JonFreeman | 1:8ef34deb5177 | 157 | pc.printf ("Looks like card newly erased, SD_blockptr value of %d\r\n", SD_blockptr); |
JonFreeman | 1:8ef34deb5177 | 158 | SD_blockptr = 0; |
JonFreeman | 1:8ef34deb5177 | 159 | historic_distance = 0; |
JonFreeman | 1:8ef34deb5177 | 160 | } |
JonFreeman | 1:8ef34deb5177 | 161 | else { |
JonFreeman | 1:8ef34deb5177 | 162 | SD_state = sd.ReadBlocks(SDBuffer, SD_BLOCKSIZE * (SD_blockptr - 1), SD_BLOCKSIZE, 1); |
JonFreeman | 1:8ef34deb5177 | 163 | if (SD_state != SD_OK) { |
JonFreeman | 1:8ef34deb5177 | 164 | pc.printf ("Error reading last block from SD block %d\r\n", SD_blockptr - 1); |
JonFreeman | 1:8ef34deb5177 | 165 | return false; |
JonFreeman | 1:8ef34deb5177 | 166 | } |
JonFreeman | 1:8ef34deb5177 | 167 | for (int i = 0; i < (SD_BLOCKSIZE >> 2); i++) |
JonFreeman | 1:8ef34deb5177 | 168 | pc.printf ("%lx\t", SDBuffer[i]); |
JonFreeman | 1:8ef34deb5177 | 169 | historic_distance = SDBuffer[(SD_BLOCKSIZE >> 2) - 1]; |
JonFreeman | 1:8ef34deb5177 | 170 | pc.printf ("\r\nAbove, data read from last filled SD block %lld, using historic_distance = %lx\r\n", SD_blockptr - 1, historic_distance); |
JonFreeman | 1:8ef34deb5177 | 171 | } |
JonFreeman | 1:8ef34deb5177 | 172 | if (SD_blockptr > 2) { |
JonFreeman | 1:8ef34deb5177 | 173 | for (int i = SD_blockptr - 2; i < SD_blockptr + 2; i++) { |
JonFreeman | 1:8ef34deb5177 | 174 | pc.printf ("check_SD_block_clear (%d) ", i); |
JonFreeman | 1:8ef34deb5177 | 175 | if (check_SD_block_clear(i)) |
JonFreeman | 1:8ef34deb5177 | 176 | pc.printf ("block %ld is CLEAR\r\n", i); |
JonFreeman | 1:8ef34deb5177 | 177 | else |
JonFreeman | 1:8ef34deb5177 | 178 | pc.printf ("block %ld is NOT clear\r\n", i); |
JonFreeman | 1:8ef34deb5177 | 179 | if (sd_error()) { |
JonFreeman | 1:8ef34deb5177 | 180 | pc.printf ("ERROR from check_SD_block_clear ()\r\n"); |
JonFreeman | 1:8ef34deb5177 | 181 | } |
JonFreeman | 1:8ef34deb5177 | 182 | } |
JonFreeman | 1:8ef34deb5177 | 183 | } |
JonFreeman | 1:8ef34deb5177 | 184 | return true; |
JonFreeman | 1:8ef34deb5177 | 185 | } |
JonFreeman | 1:8ef34deb5177 | 186 | |
JonFreeman | 1:8ef34deb5177 | 187 | void update_SD_card () { // Hall pulse total updated once per sec and saved in blocks of 128 to SD card |
JonFreeman | 1:8ef34deb5177 | 188 | static int index = 0; |
JonFreeman | 1:8ef34deb5177 | 189 | static uint32_t buff[(SD_BLOCKSIZE >> 2) + 2]; |
JonFreeman | 1:8ef34deb5177 | 190 | // buff[index++] = speed.pulse_total(); // pulse_total for all time, add this to buffer to write to SD |
JonFreeman | 1:8ef34deb5177 | 191 | buff[index++] = get_pulse_total(); // pulse_total for all time, add this to buffer to write to SD |
JonFreeman | 1:8ef34deb5177 | 192 | if (index >= (SD_BLOCKSIZE >> 2)) { |
JonFreeman | 1:8ef34deb5177 | 193 | pc.printf ("Writing new SD block %d ... ", SD_blockptr); |
JonFreeman | 1:8ef34deb5177 | 194 | SD_state = sd.WriteBlocks(buff, SD_BLOCKSIZE * SD_blockptr, SD_BLOCKSIZE, 1); |
JonFreeman | 1:8ef34deb5177 | 195 | SD_blockptr++; |
JonFreeman | 1:8ef34deb5177 | 196 | if (SD_state == SD_OK) |
JonFreeman | 1:8ef34deb5177 | 197 | pc.printf ("OK, distance %d\r\n", buff[index - 1] / (int)PULSES_PER_METRE); |
JonFreeman | 1:8ef34deb5177 | 198 | else |
JonFreeman | 1:8ef34deb5177 | 199 | pc.printf ("ERROR\r\n"); |
JonFreeman | 1:8ef34deb5177 | 200 | index = 0; |
JonFreeman | 1:8ef34deb5177 | 201 | } |
JonFreeman | 1:8ef34deb5177 | 202 | } |
JonFreeman | 1:8ef34deb5177 | 203 | |
JonFreeman | 1:8ef34deb5177 | 204 |