Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
7446dac
link: see it in action
jsoref Jan 6, 2026
5924d6e
link: emulated block device
jsoref Jan 12, 2026
9ed62ce
spelling: ; otherwise,
jsoref Jan 6, 2026
fa63f67
spelling: a
jsoref Jan 6, 2026
6640e0d
spelling: acknowledgement
jsoref Jan 6, 2026
f3cb3fc
spelling: advertising
jsoref Jan 6, 2026
d1de8d9
spelling: an
jsoref Jan 6, 2026
8b01cd4
spelling: analog
jsoref Jan 6, 2026
39e464f
spelling: app, tab
jsoref Jan 6, 2026
580e748
spelling: at
jsoref Jan 6, 2026
d1b0592
spelling: atmospheric
jsoref Jan 6, 2026
41996cc
spelling: be restored
jsoref Jan 6, 2026
90899ef
spelling: before
jsoref Jan 7, 2026
7e0d2e3
spelling: big and small
jsoref Jan 6, 2026
8ab8064
spelling: but is
jsoref Jan 9, 2026
1eb38df
spelling: buzzer
jsoref Jan 9, 2026
1c4e0af
spelling: cannot
jsoref Jan 6, 2026
3938e0f
spelling: case-insensitive
jsoref Jan 6, 2026
3b48091
spelling: command
jsoref Jan 6, 2026
0e5aa1d
spelling: consensus
jsoref Jan 6, 2026
0af6464
spelling: continuously
jsoref Jan 6, 2026
3493dfb
spelling: controls
jsoref Jan 6, 2026
bc63920
spelling: convenience
jsoref Jan 6, 2026
623853d
spelling: de-prioritize
jsoref Jan 7, 2026
01e46aa
spelling: depending
jsoref Jan 6, 2026
1f85a81
spelling: description
jsoref Jan 6, 2026
61cdbd8
spelling: directory
jsoref Jan 6, 2026
5abf7dc
spelling: display
jsoref Jan 6, 2026
5319aff
spelling: every time
jsoref Jan 6, 2026
58a277e
spelling: exceed
jsoref Jan 6, 2026
15fe6b2
spelling: exchange
jsoref Jan 6, 2026
24cfaa7
spelling: existing
jsoref Jan 6, 2026
39c8adf
spelling: fall back
jsoref Jan 6, 2026
3c01f1b
spelling: forwarded
jsoref Jan 6, 2026
e6def98
spelling: helpers
jsoref Jan 12, 2026
c1ac65e
spelling: holds
jsoref Jan 6, 2026
a934230
spelling: implementation
jsoref Jan 6, 2026
7f07b37
spelling: implemented
jsoref Jan 6, 2026
7574475
spelling: in front
jsoref Jan 9, 2026
91ba2a1
spelling: initialization
jsoref Jan 6, 2026
d07409b
spelling: its
jsoref Jan 6, 2026
3b027b0
spelling: javascript
jsoref Jan 6, 2026
555186a
spelling: length
jsoref Jan 7, 2026
536f2f6
spelling: lit
jsoref Jan 7, 2026
f488eb7
spelling: little-endian
jsoref Jan 12, 2026
517155f
spelling: location
jsoref Jan 7, 2026
a27c1ef
spelling: messages
jsoref Jan 7, 2026
270cdd0
spelling: minimum
jsoref Jan 7, 2026
41b7e5b
spelling: negligible
jsoref Jan 7, 2026
58c2552
spelling: neighbor
jsoref Jan 7, 2026
5839b5f
spelling: neighbouring
jsoref Jan 7, 2026
3dcaff7
spelling: neither-nor
jsoref Jan 12, 2026
66b9a33
spelling: node
jsoref Jan 7, 2026
9d17657
spelling: nonexistent
jsoref Jan 6, 2026
fed4f35
spelling: occurred
jsoref Jan 7, 2026
0522db2
spelling: on
jsoref Jan 7, 2026
7046258
spelling: one
jsoref Jan 6, 2026
f4d8f39
spelling: periodically
jsoref Jan 7, 2026
54e64b1
spelling: persistent
jsoref Jan 7, 2026
b3d9317
spelling: power
jsoref Jan 7, 2026
e7dca52
spelling: process
jsoref Jan 7, 2026
c173ffb
spelling: propagated
jsoref Jan 7, 2026
ae95384
spelling: query
jsoref Jan 7, 2026
0dc53df
spelling: received
jsoref Jan 7, 2026
6dadaf9
spelling: recent
jsoref Jan 7, 2026
2ed1d67
spelling: recognizes
jsoref Jan 12, 2026
7f6fea3
spelling: safely
jsoref Jan 7, 2026
9bc7470
spelling: separator
jsoref Jan 7, 2026
352383f
spelling: set up
jsoref Jan 12, 2026
039baa2
spelling: shouldn't
jsoref Jan 7, 2026
59eb006
spelling: supported
jsoref Jan 7, 2026
f528e70
spelling: that
jsoref Jan 6, 2026
acb1ff2
spelling: the first time you send a message
jsoref Jan 6, 2026
95098dd
spelling: timestamp
jsoref Jan 7, 2026
b81a427
spelling: transport
jsoref Jan 7, 2026
50862a9
spelling: unknown
jsoref Jan 7, 2026
4619792
spelling: unnecessary
jsoref Jan 7, 2026
60f8f4f
spelling: unsupported
jsoref Jan 7, 2026
81fa60f
spelling: unused
jsoref Jan 7, 2026
8f85c29
spelling: using
jsoref Jan 6, 2026
b9415d1
spelling: whether
jsoref Jan 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Please submit PR's using 'dev' as the base branch!
For minor changes just submit your PR and I'll try to review it, but for anything more 'impactful' please open an Issue first and start a discussion. Is better to sound out what it is you want to achieve first, and try to come to a consensus on what the best approach is, especially when it impacts the structure or architecture of this codebase.

Here are some general principals you should try to adhere to:
* Keep it simple. Please, don't think like a high-level lang programmer. Think embedded, and keep code concise, without any unecessary layers.
* Keep it simple. Please, don't think like a high-level lang programmer. Think embedded, and keep code concise, without any unnecessary layers.
* No dynamic memory allocation, except during setup/begin functions.
* Use the same brace and indenting style that's in the core source modules. (A .clang-format is prob going to be added soon, but please do NOT retroactively re-format existing code. This just creates unnecessary diffs that make finding problems harder)

Expand All @@ -106,7 +106,7 @@ There are a number of fairly major features in the pipeline, with no particular
- [ ] Core + Apps: support for LZW message compression
- [ ] Core: dynamic CR (Coding Rate) for weak vs strong hops
- [ ] Core: new framework for hosting multiple virtual nodes on one physical device
- [ ] V2 protocol spec: discussion and concensus around V2 packet protocol, including path hashes, new encryption specs, etc
- [ ] V2 protocol spec: discussion and consensus around V2 packet protocol, including path hashes, new encryption specs, etc

## 📞 Get Support

Expand Down
4 changes: 2 additions & 2 deletions arch/stm32/Adafruit_LittleFS_stm32/src/Adafruit_LittleFS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ bool Adafruit_LittleFS::begin (struct lfs_config * cfg)
_lockFS();

bool ret;
// not a loop, just an quick way to short-circuit on error
// not a loop, just a quick way to short-circuit on error
do {
if (_mounted) { ret = true; break; }
if (cfg) { _lfs_cfg = cfg; }
Expand Down Expand Up @@ -102,7 +102,7 @@ bool Adafruit_LittleFS::format (void)

int err = LFS_ERR_OK;
bool attemptMount = _mounted;
// not a loop, just an quick way to short-circuit on error
// not a loop, just a quick way to short-circuit on error
do
{
// if already mounted: umount first -> format -> remount
Expand Down
8 changes: 4 additions & 4 deletions arch/stm32/Adafruit_LittleFS_stm32/src/littlefs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ storage on disk is always kept in a valid state.

**Wear leveling** - Since the most common form of embedded storage is erodible
flash memories, littlefs provides a form of dynamic wear leveling for systems
that can not fit a full flash translation layer.
that cannot fit a full flash translation layer.

## Example

Expand Down Expand Up @@ -123,7 +123,7 @@ integrity.

If your storage caches writes, make sure that the provided `sync` function
flushes all the data to memory and ensures that the next read fetches the data
from memory, otherwise data integrity can not be guaranteed. If the `write`
from memory; otherwise, data integrity cannot be guaranteed. If the `write`
function does not perform caching, and therefore each `read` or `write` call
hits the memory, the `sync` function can simply return 0.

Expand All @@ -139,7 +139,7 @@ with all the nitty-gritty details. Can be useful for developing tooling.
## Testing

The littlefs comes with a test suite designed to run on a PC using the
[emulated block device](emubd/lfs_emubd.h) found in the emubd directory.
[emulated block device](https://github.com/littlefs-project/littlefs/blob/master/bd/lfs_emubd.h).
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is notable. There is no sign that emubd/lfs_emubd.h was ever in this repository...

The tests assume a Linux environment and can be started with make:

``` bash
Expand Down Expand Up @@ -174,4 +174,4 @@ handy.

[littlefs-js](https://github.com/geky/littlefs-js) - A javascript wrapper for
littlefs. I'm not sure why you would want this, but it is handy for demos.
You can see it in action [here](http://littlefs.geky.net/demo.html).
You can [see it in action](http://littlefs.geky.net/demo.html).
12 changes: 6 additions & 6 deletions arch/stm32/Adafruit_LittleFS_stm32/src/littlefs/lfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir) {

static int lfs_dir_fetch(lfs_t *lfs,
lfs_dir_t *dir, const lfs_block_t pair[2]) {
// copy out pair, otherwise may be aliasing dir
// copy out pair; otherwise, may be aliasing dir
const lfs_block_t tpair[2] = {pair[0], pair[1]};
bool valid = false;

Expand Down Expand Up @@ -482,7 +482,7 @@ static int lfs_dir_fetch(lfs_t *lfs,

valid = true;

// setup dir in case it's valid
// set up dir in case it's valid
dir->pair[0] = tpair[(i+0) % 2];
dir->pair[1] = tpair[(i+1) % 2];
dir->off = sizeof(dir->d);
Expand Down Expand Up @@ -2328,7 +2328,7 @@ static int lfs_pred(lfs_t *lfs, const lfs_block_t dir[2], lfs_dir_t *pdir) {
return 0;
}

// iterate over all directory directory entries
// iterate over all directory entries
int err = lfs_dir_fetch(lfs, pdir, (const lfs_block_t[2]){0, 1});
if (err) {
return err;
Expand Down Expand Up @@ -2357,7 +2357,7 @@ static int lfs_parent(lfs_t *lfs, const lfs_block_t dir[2],
parent->d.tail[0] = 0;
parent->d.tail[1] = 1;

// iterate over all directory directory entries
// iterate over all directory entries
while (!lfs_pairisnull(parent->d.tail)) {
int err = lfs_dir_fetch(lfs, parent, parent->d.tail);
if (err) {
Expand Down Expand Up @@ -2396,7 +2396,7 @@ static int lfs_moved(lfs_t *lfs, const void *e) {
return err;
}

// iterate over all directory directory entries
// iterate over all directory entries
lfs_entry_t entry;
while (!lfs_pairisnull(cwd.d.tail)) {
err = lfs_dir_fetch(lfs, &cwd, cwd.d.tail);
Expand Down Expand Up @@ -2484,7 +2484,7 @@ int lfs_deorphan(lfs_t *lfs) {
lfs_dir_t pdir = {.d.size = 0x80000000};
lfs_dir_t cwd = {.d.tail[0] = 0, .d.tail[1] = 1};

// iterate over all directory directory entries
// iterate over all directory entries
for (lfs_size_t i = 0; i < lfs->cfg->block_count; i++) {
if (lfs_pairisnull(cwd.d.tail)) {
return 0;
Expand Down
12 changes: 6 additions & 6 deletions arch/stm32/Adafruit_LittleFS_stm32/src/littlefs/lfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ enum lfs_open_flags {
LFS_F_DIRTY = 0x10000, // File does not match storage
LFS_F_WRITING = 0x20000, // File has been written since last flush
LFS_F_READING = 0x40000, // File has been read since last flush
LFS_F_ERRED = 0x80000, // An error occured during write
LFS_F_ERRED = 0x80000, // An error occurred during write
};

// File seek flags
Expand All @@ -111,25 +111,25 @@ struct lfs_config {
// information to the block device operations
void *context;

// Read a region in a block. Negative error codes are propogated
// Read a region in a block. Negative error codes are propagated
// to the user.
int (*read)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size);

// Program a region in a block. The block must have previously
// been erased. Negative error codes are propogated to the user.
// been erased. Negative error codes are propagated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*prog)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size);

// Erase a block. A block must be erased before being programmed.
// The state of an erased block is undefined. Negative error codes
// are propogated to the user.
// are propagated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*erase)(const struct lfs_config *c, lfs_block_t block);

// Sync the state of the underlying block device. Negative error codes
// are propogated to the user.
// are propagated to the user.
int (*sync)(const struct lfs_config *c);

// Minimum size of a block read. This determines the size of read buffers.
Expand Down Expand Up @@ -484,7 +484,7 @@ int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
// Returns a negative error code on failure.
int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);

// Prunes any recoverable errors that may have occured in the filesystem
// Prunes any recoverable errors that may have occurred in the filesystem
//
// Not needed to be called by user unless an operation is interrupted
// but the filesystem is still mounted. This is already called on first
Expand Down
4 changes: 2 additions & 2 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ get_pio_envs() {
echo $(pio project config | grep 'env:' | sed 's/env://')
}

# $1 should be the string to find (case insensitive)
# $1 should be the string to find (case-insensitive)
get_pio_envs_containing_string() {
shopt -s nocasematch
envs=($(get_pio_envs))
Expand All @@ -57,7 +57,7 @@ get_pio_envs_containing_string() {
done
}

# $1 should be the string to find (case insensitive)
# $1 should be the string to find (case-insensitive)
get_pio_envs_ending_with_string() {
shopt -s nocasematch
envs=($(get_pio_envs))
Expand Down
18 changes: 9 additions & 9 deletions docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ author: https://github.com/LitBomb<!-- omit from toc -->
- [3.3. Q: What is the password to administer a repeater or a room server?](#33-q-what-is-the-password-to-administer-a-repeater-or-a-room-server)
- [3.4. Q: What is the password to join a room server?](#34-q-what-is-the-password-to-join-a-room-server)
- [3.5. Q: Can I retrieve a repeater's private key or set a repeater's private key?](#35-q-can-i-retrieve-a-repeaters-private-key-or-set-a-repeaters-private-key)
- [3.6. Q: The first byte of my repeater's public key collides with an exisitng repeater on the mesh. How do I get a new private key with a matching public key that has its first byte of my choosing?](#36-q-the-first-byte-of-my-repeaters-public-key-collides-with-an-exisitng-repeater-on-the-mesh--how-do-i-get-a-new-private-key-with-a-matching-public-key-that-has-its-first-byte-of-my-choosing)
- [3.6. Q: The first byte of my repeater's public key collides with an existing repeater on the mesh. How do I get a new private key with a matching public key that has its first byte of my choosing?](#36-q-the-first-byte-of-my-repeaters-public-key-collides-with-an-existing-repeater-on-the-mesh--how-do-i-get-a-new-private-key-with-a-matching-public-key-that-has-its-first-byte-of-my-choosing)
- [3.7. Q: My repeater maybe suffering from deafness due to high power interference near my mesh's frequency, it is not hearing other in-range MeshCore radios. what can I do?](#37-q-my-repeater-maybe-suffering-from-deafness-due-to-high-power-interference-near-my-meshs-frequency-it-is-not-hearing-other-in-range-meshcore-radios--what-can-i-do)
- [3.8 Q: How do I make my repeater an observer on the mesh](#38-q-how-do-i-make-my-repeater-an-observer-on-the-mesh)
- [4. T-Deck Related](#4-t-deck-related)
Expand Down Expand Up @@ -158,7 +158,7 @@ A room server can be remotely administered using a T-Deck running the MeshCore f

When a client logs into a room server, the client will receive the previously 32 unseen messages.

Although room server can also repeat with the command line command `set repeat on`, it is not recommended nor encouraged. A room server with repeat set to `on` lacks the full set of repeater and remote administration features that are only available in the repeater firmware.
Although room server can also repeat with the command line command `set repeat on`, it is neither recommended nor encouraged. A room server with repeat set to `on` lacks the full set of repeater and remote administration features that are only available in the repeater firmware.

The recommendation is to run repeater and room server on separate devices for the best experience.

Expand Down Expand Up @@ -277,14 +277,14 @@ You can get the latitude and longitude from Google Maps by right-clicking the lo

Reboot the repeater after `set prv.key <hex>` command for the new private key to take effect.

### 3.6. Q: The first byte of my repeater's public key collides with an exisitng repeater on the mesh. How do I get a new private key with a matching public key that has its first byte of my choosing?
### 3.6. Q: The first byte of my repeater's public key collides with an existing repeater on the mesh. How do I get a new private key with a matching public key that has its first byte of my choosing?

**A:** You can generate a new private key and specific the first byte of its public key here: https://gessaman.com/mc-keygen/


### 3.7. Q: My repeater maybe suffering from deafness due to high power interference near my mesh's frequency, it is not hearing other in-range MeshCore radios. what can I do?

**A:** This may be due to the SX1262 radio's auto gain control feature. You can use this command to preiodically reset its AGC.
**A:** This may be due to the SX1262 radio's auto gain control feature. You can use this command to periodically reset its AGC.

`set agc.reset.interval <number>`

Expand Down Expand Up @@ -450,7 +450,7 @@ In the case if users are moving around frequently, and the paths are breaking, t

### 5.4. Q: How does a node discovery a path to its destination and then use it to send messages in the future, instead of flooding every message it sends like Meshtastic?

Routes are stored in sender's contact list. When you send a message the first time, the message first gets to your destination by flood routing. When your destination node gets the message, it will send back a delivery report to the sender with all repeaters that the original message went through. This delivery report is flood-routed back to you the sender and is a basis for future direct path. When you send the next message, the path will get embedded into the packet and be evaluated by repeaters. If the hop and address of the repeater matches, it will retransmit the message, otherwise it will not retransmit, hence minimizing utilization.
Routes are stored in sender's contact list. The first time you send a message, the message first gets to your destination by flood routing. When your destination node gets the message, it will send back a delivery report to the sender with all repeaters that the original message went through. This delivery report is flood-routed back to you the sender and is a basis for future direct path. When you send the next message, the path will get embedded into the packet and be evaluated by repeaters. If the hop and address of the repeater matches, it will retransmit the message; otherwise, it will not retransmit, hence minimizing utilization.

[Source](https://discord.com/channels/826570251612323860/1330643963501351004/1351279141630119996)

Expand Down Expand Up @@ -518,10 +518,10 @@ Andy also has a video on how to build using VS Code:

### 5.10. Q: Are there other MeshCore related open source projects?

**A:** [Liam Cottle](https://liamcottle.net)'s MeshCore web client and MeshCore Javascript library are open source under MIT license.
**A:** [Liam Cottle](https://liamcottle.net)'s MeshCore web client and MeshCore JavaScript library are open source under MIT license.

Web client: https://github.com/liamcottle/meshcore-web
Javascript: https://github.com/liamcottle/meshcore.js
JavaScript: https://github.com/liamcottle/meshcore.js

### 5.11. Q: Does MeshCore support ATAK
**A:** ATAK is not currently on MeshCore's roadmap.
Expand Down Expand Up @@ -733,7 +733,7 @@ Allow the browser user on it:
3. From the MeshCore app, login remotely to the repeater you want to update with admin privilege
4. Go to the Command Line tab, type `start ota` and hit enter.
5. you should see `OK` to confirm the repeater device is now in OTA mode
6. Run the DFU app,tab `Settings` on the top right corner
6. Run the DFU app, tab `Settings` at the top right corner
7. Enable `Packets receipt notifications`, and change `Number of Packets` to 10 for RAK, 8 for T114. 8 also works for RAK.
9. Select the firmware zip file you downloaded
10. Select the device you want to update. If the device you want to update is not on the list, try enabling`OTA` on the device again
Expand Down Expand Up @@ -804,7 +804,7 @@ Edit WIFI_SSID and WIFI_PWD in `./variants/heltec_v3/platformio.ini` and then fl

### 7.7. Q: I have a Station G2, or a Heltec V4, or an Ikoka Stick, or a radio with a EByte E22-900M30S or a E22-900M33S module, what should their transmit power be set to?
**A:**
For companion radios, you can set these radios' transmit power in the smartphone app. For repeater and room server radios, you can set their transmit power using the command line command `set tx`. You can get their current value using command line comand `get tx`
For companion radios, you can set these radios' transmit power in the smartphone app. For repeater and room server radios, you can set their transmit power using the command line command `set tx`. You can get their current value using command line command `get tx`


> ### ⚠️ **WARNING: Set these values at your own risk. Incorrect power settings can permanently damage your radio hardware.**
Expand Down
6 changes: 3 additions & 3 deletions docs/payloads.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Inside of each [meshcore packet](./packet_structure.md) is a payload, identified

This document defines the structure of each of these payload types.

NOTE: all 16 and 32-bit integer fields are Little Endian.
NOTE: all 16 and 32-bit integer fields are Little-Endian.

## Important concepts:

Expand Down Expand Up @@ -58,7 +58,7 @@ Appdata Flags

# Acknowledgement

An acknowledgement that a message was received. Note that for returned path messages, an acknowledgement can be sent in the "extra" payload (see [Returned Path](#returned-path)) instead of as a separate ackowledgement packet. CLI commands do not cause acknowledgement responses, neither discrete nor extra.
An acknowledgement that a message was received. Note that for returned path messages, an acknowledgement can be sent in the "extra" payload (see [Returned Path](#returned-path)) instead of as a separate acknowledgement packet. CLI commands do not cause acknowledgement responses, neither discrete nor extra.

| Field | Size (bytes) | Description |
|----------|--------------|------------------------------------------------------------|
Expand All @@ -78,7 +78,7 @@ Returned path, request, response, and plain text messages are all formatted in t

## Returned path

Returned path messages provide a description of the route a packet took from the original author. Receivers will send returned path messages to the author of the original message.
Returned path messages provide a description of the route that a packet took from the original author. Receivers will send returned path messages to the author of the original message.

| Field | Size (bytes) | Description |
|-------------|--------------|----------------------------------------------------------------------------------------------|
Expand Down
2 changes: 1 addition & 1 deletion examples/companion_radio/DataStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ bool DataStore::putBlobByKey(const uint8_t key[], int key_len, const uint8_t src
uint32_t pos = 0, found_pos = 0;
uint32_t min_timestamp = 0xFFFFFFFF;

// search for matching key OR evict by oldest timestmap
// search for matching key OR evict by oldest timestamp
BlobRec tmp;
file.seek(0);
while (file.read((uint8_t *) &tmp, sizeof(tmp)) == sizeof(tmp)) {
Expand Down
Loading