Hacker Newsnew | past | comments | ask | show | jobs | submit | noexani's commentslogin

You are correct. the conversion to Celsius * 10 is done earlier on, because it is easy to optionally perform this conversion, and it's easy to render the various formats (positive/negative/DP,no DP) of it to the 7-segment display banks.

Also worth considering that I originally had no interest in fahrenheit (I live in the UK). This was done as an extra later on. Didn't want to poo the original implementation taking fahrenheit straight off the sensors.


OK, I understand. The approach works even better if you multiply by 10:

  int16_t celsius2fahrenheit10(int16_t c)
  {
    int16_t f = 0;
    f += c << 4;
    f -= c;
    f -= c >> 1;
    f -= c >> 3;
    f += c >> 5;
    f += 320 * 8;
    f >>= 3;
    return f;
  }
This is really accurate:

  C=0    (int 0)    F=32   (int: 320,  exact: 32)
  C=15.3 (int 153)  F=59.5 (int: 595,  exact: 59.54)
  C=37   (int 370)  F=98.6 (int: 986,  exact: 98.6)
  C=100  (int 1000) F=212  (int: 2120, exact: 212)


It's really interesting to see that it could be done like that, but, that pseudo code you've given me would translate to a heck of a lot of MCS-48 instructions! 16-bit subtraction in particular is really expensive. Potentially not much gain there?


This is the same code in MCS48 assembly. Or so I hope.

  ; INPUT:  r1:r0  celsius * 10
  ; OUTPUT: r3:r2  fahrenheit * 10

  MOV A, r0
  ADD A, r0
  MOV r2, A
  MOV r4, A
  MOV A, r1
  RLC A
  MOV r3, A
  MOV r5, A
  MOV A, r4
  ADD A, r4
  XCH A, r5
  RLC A
  MOV r4, A
  MOV A, r2
  ADD A, r5
  XCH A, r3
  ADDC A, r4
  MOV r2, A
  MOV A, r5
  ADD A, r5
  XCH A, r4
  RLC A
  MOV r5, A
  MOV A, r3
  ADD A, r4
  XCH A, r2
  ADDC A, r5
  MOV r3, A
  MOV A, r1
  ADD A, r1
  MOV A, r1
  RRC A
  MOV r5, A
  MOV A, r0
  RRC A
  MOV r4, A
  MOV A, r5
  ADD A, r5
  MOV A, r5
  RRC A
  XCH A, r4
  RRC A
  MOV r5, A
  MOV A, r2
  ADD A, r5
  XCH A, r3
  ADDC A, r4
  MOV r2, A
  MOV A, r4
  ADD A, r4
  MOV A, r4
  RRC A
  XCH A, r5
  RRC A
  MOV r4, A
  MOV A, r3
  ADD A, r4
  XCH A, r2
  ADDC A, r5
  MOV r3, A
  MOV A, r5
  ADD A, r5
  MOV A, r5
  RRC A
  XCH A, r4
  RRC A
  MOV r5, A
  MOV A, r4
  ADD A, r4
  MOV A, r4
  RRC A
  XCH A, r5
  RRC A
  MOV r4, A
  MOV A, r2
  ADD A, r4
  XCH A, r3
  ADDC A, r5
  ADD A, 10
  MOV r2, A
  ADD A, r2
  MOV A, r2
  RRC A
  XCH A, r3
  RRC A
  MOV r2, A
  MOV A, r3
  ADD A, r3
  MOV A, r3
  RRC A
  XCH A, r2
  RRC A
  MOV r3, A
  MOV A, r2
  ADD A, r2
  MOV A, r2
  RRC A
  XCH A, r3
  RRC A
  MOV r2, A


But you do have CPL -- that does not help? Anyway, without subtraction, you could do the very same with one additional add:

  int16_t celsius2fahrenheit(int16_t c)
  {
    int16_t f = 0;
    f += c << 1;
    f += c << 2;
    f += c << 3;
    f += c >> 2;
    f += c >> 3;
    f += c >> 5;
    f += 320 * 8;
    f >>= 3;
    return f;
  }


I have done some MCS-48 reverse engineering too. It's really useful to look at the snippets in that manual as you'll find them in disassembled code, making it quite a bit easier to understand.


It depends on the application. In this case a lookup table would consume quite a bit more program memory (there isn't any spare), and the division routine is needed for other tasks, so it makes sense to use it for that conversion too. Speed is not an issue.


I just calculated, there are 1800 possible Celsius values. in this application. That would be quite some lookup table.


You can very likely compress the table and/or interpolate between entries. It's not like that those entries are totally random.


You can actually do that as well with the division itself. But you need a kind of fancy interpolation, I forget the name, used for rational functions. Polynomials won't do.

Edit: I think this is either Restrictive Pade's approximation or barycentric rational interpolation. Or both combined.

Normally instead division is approximated with Newton-Raphson iteration. I think 6 steps is enough for 16 bit.


It's a simple linear function, and the delta Y has enough digits to overcome significant rounding error in comparison to measurement error.

In this application no rounding is needed either since the difference between rounding and truncation is also not significant.

You don't need the computer to do any of your multiplication or store any table.

You can start from a sufficiently low reference point, then add delta Y as you increment X.

Xref + deltaX = Yref + deltaY


Ah yes. Another one of those 'why the heck is my blog running so slow today' days.

It's on Hackernews (again) Are people ever going to get over this page?


DS18B20 one-wire bus temperature sensor with old school LED 7 segment displays


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: