Unlike some earlier protocols which used packet sequence numbers, TCP connections use byte sequence numbers. Each packet essentially says "I have received the data stream from you up to but not including byte A; I would be interested in seeing up to W bytes beyond that. Here are N bytes from me starting with sequence number T". The byte sequence numbers are 32 bits, and are initialized to an arbitrary value when a connection is opened, and they wrap from 0xFFFFFFFF to 0; when comparing sequence numbers, one should generally subtract using unsigned values, and then look at the result as an unsigned value.
Typically, an implementation will keep track of the sequence number of the next byte it expects, the highest sequence number for which it has received an acknowledgment, the sequence number of the last byte transmitted, how long it should wait for an acknowledgment before retransmitting, and how long it should wait for more data before acknowledging what it has.
Any time the data has data to send which the other unit would be interested in, it should send it and setting the timer for expect an acknowledgment if it isn't already running. Any time it receives an acknowledgment for some but not all of the data it has sent, it should reset that timer. Any time that timer expires without having received an acknowledgment for all data, the unit should load its "last byte transmitted" sequence number with the highest sequence number for which it has received an acknowledgment.
If data arrives with the incoming packets, the unit should set a timer to acknowledge it. When the timer expires, the unit should send out a packet even if it doesn't have any data of its own to send. If the unit sends out a packet for any other reason, it can acknowledge all data received up to that point, and may thus cancel the acknowledgement timer.
Note that it's possible for many packets' worth of data to be acknowledged by a single return acknowledgment; it's also possible that data which was sent out as multiple packets may get retransmitted as one larger packet. Units should expect that they may receive a packet containing a mixture of old and new data; they should simply process the new data and ignore the old. Note that units should acknowledge data they receive whether or not any of it was 'new'; the acknowledgement should indicate the sequence number of the next expected byte, regardless of what data was in the packet being acknowledged.
TCP is in many ways a fairly simple protocol, although newer implementations include a lot of "optional" wrinkles. Generally, devices like embedded microcontrollers can get by with implementing a small subset of the features that full-fledged PC's are likely to include.